Croniter provides iteration for the datetime object with a cron like format

Overview

Introduction

croniter provides iteration for the datetime object with a cron like format.

                      _ _
  ___ _ __ ___  _ __ (_) |_ ___ _ __
 / __| '__/ _ \| '_ \| | __/ _ \ '__|
| (__| | | (_) | | | | | ||  __/ |
 \___|_|  \___/|_| |_|_|\__\___|_|

Website: https://github.com/kiorky/croniter

Travis badge

https://travis-ci.org/kiorky/croniter.svg?branch=master

Usage

A simple example:

>>> from croniter import croniter
>>> from datetime import datetime
>>> base = datetime(2010, 1, 25, 4, 46)
>>> iter = croniter('*/5 * * * *', base)  # every 5 minutes
>>> print(iter.get_next(datetime))   # 2010-01-25 04:50:00
>>> print(iter.get_next(datetime))   # 2010-01-25 04:55:00
>>> print(iter.get_next(datetime))   # 2010-01-25 05:00:00
>>>
>>> iter = croniter('2 4 * * mon,fri', base)  # 04:02 on every Monday and Friday
>>> print(iter.get_next(datetime))   # 2010-01-26 04:02:00
>>> print(iter.get_next(datetime))   # 2010-01-30 04:02:00
>>> print(iter.get_next(datetime))   # 2010-02-02 04:02:00
>>>
>>> iter = croniter('2 4 1 * wed', base)  # 04:02 on every Wednesday OR on 1st day of month
>>> print(iter.get_next(datetime))   # 2010-01-27 04:02:00
>>> print(iter.get_next(datetime))   # 2010-02-01 04:02:00
>>> print(iter.get_next(datetime))   # 2010-02-03 04:02:00
>>>
>>> iter = croniter('2 4 1 * wed', base, day_or=False)  # 04:02 on every 1st day of the month if it is a Wednesday
>>> print(iter.get_next(datetime))   # 2010-09-01 04:02:00
>>> print(iter.get_next(datetime))   # 2010-12-01 04:02:00
>>> print(iter.get_next(datetime))   # 2011-06-01 04:02:00
>>>
>>> iter = croniter('0 0 * * sat#1,sun#2', base)  # 1st Saturday, and 2nd Sunday of the month
>>> print(iter.get_next(datetime))   # 2010-02-06 00:00:00
>>>
>>> iter = croniter('0 0 * * 5#3,L5', base)  # 3rd and last Friday of the month
>>> print(iter.get_next(datetime))   # 2010-01-29 00:00:00
>>> print(iter.get_next(datetime))   # 2010-02-19 00:00:00

All you need to know is how to use the constructor and the get_next method, the signature of these methods are listed below:

>>> def __init__(self, cron_format, start_time=time.time(), day_or=True)

croniter iterates along with cron_format from start_time. cron_format is min hour day month day_of_week, you can refer to http://en.wikipedia.org/wiki/Cron for more details. The day_or switch is used to control how croniter handles day and day_of_week entries. Default option is the cron behaviour, which connects those values using OR. If the switch is set to False, the values are connected using AND. This behaves like fcron and enables you to e.g. define a job that executes each 2nd friday of a month by setting the days of month and the weekday.

>>> def get_next(self, ret_type=float)

get_next calculates the next value according to the cron expression and returns an object of type ret_type. ret_type should be a float or a datetime object.

Supported added for get_prev method. (>= 0.2.0):

>>> base = datetime(2010, 8, 25)
>>> itr = croniter('0 0 1 * *', base)
>>> print(itr.get_prev(datetime))  # 2010-08-01 00:00:00
>>> print(itr.get_prev(datetime))  # 2010-07-01 00:00:00
>>> print(itr.get_prev(datetime))  # 2010-06-01 00:00:00

You can validate your crons using is_valid class method. (>= 0.3.18):

>>> croniter.is_valid('0 0 1 * *')  # True
>>> croniter.is_valid('0 wrong_value 1 * *')  # False

About DST

Be sure to init your croniter instance with a TZ aware datetime for this to work!

Example using pytz:

>>> import pytz
>>> tz = pytz.timezone("Europe/Paris")
>>> local_date = tz.localize(datetime(2017, 3, 26))
>>> val = croniter('0 0 * * *', local_date).get_next(datetime)

Example using python_dateutil:

>>> import dateutil.tz
>>> tz = dateutil.tz.gettz('Asia/Tokyo')
>>> local_date = datetime(2017, 3, 26, tzinfo=tz)
>>> val = croniter('0 0 * * *', local_date).get_next(datetime)

About second repeats

Croniter is able to do second repeatition crontabs form:

>>> croniter('* * * * * 1', local_date).get_next(datetime)
>>> base = datetime(2012, 4, 6, 13, 26, 10)
>>> itr = croniter('* * * * * 15,25', base)
>>> itr.get_next(datetime) # 4/6 13:26:15
>>> itr.get_next(datetime) # 4/6 13:26:25
>>> itr.get_next(datetime) # 4/6 13:27:15

You can also note that this expression will repeat every second from the start datetime.:

>>> croniter('* * * * * *', local_date).get_next(datetime)

Testing if a date matches a crontab

Test for a match with (>=0.3.32):

>>> croniter.match("0 0 * * *", datetime(2019, 1, 14, 0, 0, 0, 0))
True
>>> croniter.match("0 0 * * *", datetime(2019, 1, 14, 0, 2, 0, 0))
False
>>>
>>> croniter.match("2 4 1 * wed", datetime(2019, 1, 1, 4, 2, 0, 0)) # 04:02 on every Wednesday OR on 1st day of month
True
>>> croniter.match("2 4 1 * wed", datetime(2019, 1, 1, 4, 2, 0, 0), day_or=False) # 04:02 on every 1st day of the month if it is a Wednesday
False

Gaps between date matches

For performance reasons, croniter limits the amount of CPU cycles spent attempting to find the next match. Starting in v0.3.35, this behavior is configurable via the max_years_between_matches parameter, and the default window has been increased from 1 year to 50 years.

The defaults should be fine for many use cases. Applications that evaluate multiple cron expressions or handle cron expressions from untrusted sources or end-users should use this parameter. Iterating over sparse cron expressions can result in increased CPU consumption or a raised CroniterBadDateError exception which indicates that croniter has given up attempting to find the next (or previous) match. Explicitly specifying max_years_between_matches provides a way to limit CPU utilization and simplifies the iterable interface by eliminating the need for CroniterBadDateError. The difference in the iterable interface is based on the reasoning that whenever max_years_between_matches is explicitly agreed upon, there is no need for croniter to signal that it has given up; simply stopping the iteration is preferable.

This example matches 4 AM Friday, January 1st. Since January 1st isn't often a Friday, there may be a few years between each occurrence. Setting the limit to 15 years ensures all matches:

>>> it = croniter("0 4 1 1 fri", datetime(2000,1,1), day_or=False, max_years_between_matches=15).all_next(datetime)
>>> for i in range(5):
...     print(next(it))
...
2010-01-01 04:00:00
2016-01-01 04:00:00
2021-01-01 04:00:00
2027-01-01 04:00:00
2038-01-01 04:00:00

However, when only concerned with dates within the next 5 years, simply set max_years_between_matches=5 in the above example. This will result in no matches found, but no additional cycles will be wasted on unwanted matches far in the future.

Iterating over a range using cron

Find matches within a range using the croniter_range() function. This is much like the builtin range(start,stop,step) function, but for dates. The step argument is a cron expression. Added in (>=0.3.34)

List the first Saturday of every month in 2019:

>>> from croniter import croniter_range
>>> for dt in croniter_range(datetime(2019, 1, 1), datetime(2019, 12, 31), "0 0 * * sat#1"):
>>>     print(dt)

Hashed expressions

croniter supports Jenkins-style hashed expressions, using the "H" definition keyword and the required hash_id keyword argument. Hashed expressions remain consistent, given the same hash_id, but different hash_ids will evaluate completely different to each other. This allows, for example, for an even distribution of differently-named jobs without needing to manually spread them out.

>> itr.get_next(datetime) datetime.datetime(2021, 4, 10, 11, 10) >>> itr.get_next(datetime) datetime.datetime(2021, 4, 11, 11, 10) >>> itr = croniter("H H * * *", hash_id="hello") >>> itr.get_next(datetime) datetime.datetime(2021, 4, 10, 11, 10) >>> itr = croniter("H H * * *", hash_id="bonjour") >>> itr.get_next(datetime) datetime.datetime(2021, 4, 10, 20, 52) ">
>>> itr = croniter("H H * * *", hash_id="hello")
>>> itr.get_next(datetime)
datetime.datetime(2021, 4, 10, 11, 10)
>>> itr.get_next(datetime)
datetime.datetime(2021, 4, 11, 11, 10)
>>> itr = croniter("H H * * *", hash_id="hello")
>>> itr.get_next(datetime)
datetime.datetime(2021, 4, 10, 11, 10)
>>> itr = croniter("H H * * *", hash_id="bonjour")
>>> itr.get_next(datetime)
datetime.datetime(2021, 4, 10, 20, 52)

Random expressions

Random "R" definition keywords are supported, and remain consistent only within their croniter() instance.

>> itr.get_next(datetime) datetime.datetime(2021, 4, 10, 22, 56) >>> itr.get_next(datetime) datetime.datetime(2021, 4, 11, 22, 56) >>> itr = croniter("R R * * *") >>> itr.get_next(datetime) datetime.datetime(2021, 4, 11, 4, 19) ">
>>> itr = croniter("R R * * *")
>>> itr.get_next(datetime)
datetime.datetime(2021, 4, 10, 22, 56)
>>> itr.get_next(datetime)
datetime.datetime(2021, 4, 11, 22, 56)
>>> itr = croniter("R R * * *")
>>> itr.get_next(datetime)
datetime.datetime(2021, 4, 11, 4, 19)

Keyword expressions

Vixie cron-style "@" keyword expressions are supported. What they evaluate to depends on whether you supply hash_id: no hash_id corresponds to Vixie cron definitions (exact times, minute resolution), while with hash_id corresponds to Jenkins definitions (hashed within the period, second resolution).

Keyword No hash_id With hash_id
@midnight 0 0 * * * H H(0-2) * * * H
@hourly 0 * * * * H * * * * H
@daily 0 0 * * * H H * * * H
@weekly 0 0 * * 0 H H * * H H
@monthly 0 0 1 * * H H H * * H
@yearly 0 0 1 1 * H H H H * H
@annually 0 0 1 1 * H H H H * H

Develop this package

git clone https://github.com/kiorky/croniter.git
cd croniter
virtualenv --no-site-packages venv
. venv/bin/activate
pip install --upgrade -r requirements/test.txt
py.test src

Make a new release

We use zest.fullreleaser, a great release infrastructure.

Do and follow these instructions

. venv/bin/activate
pip install --upgrade -r requirements/release.txt
./release.sh

Contributors

Thanks to all who have contributed to this project! If you have contributed and your name is not listed below please let me know.

  • mrmachine
  • Hinnack
  • shazow
  • kiorky
  • jlsandell
  • mag009
  • djmitche
  • GreatCombinator
  • chris-baynes
  • ipartola
  • yuzawa-san
  • lowell80 (Kintyre)
  • scop
  • zed2015
  • Ryan Finnie (rfinnie)
Comments
  • Incorrect validation of cron time

    Incorrect validation of cron time

    Hello, everyone. I found a bug at work and it is related to the validation of the cron expression. I have 0 days and 0 months, but your method says "True". Can you explain to me if i'm wrong? image

    opened by leemurus 6
  • > Why does get_next() return a real day for the incorrect cron expression? (1 jan for '0 0 0 0 0')

    > Why does get_next() return a real day for the incorrect cron expression? (1 jan for '0 0 0 0 0')

    But the question is - why does get_next() return a real day for the incorrect cron expression? (1 jan for '0 0 0 0 0')

    This is not what the OP saidf in the first place, the OP said in the first place that is_valid returns True which is legit.

    Originally posted by @kiorky in https://github.com/kiorky/croniter/issues/5#issuecomment-985542732

    opened by mikhail-kashirskii 5
  • Cannot use croniter with cron having 7 subexpression

    Cannot use croniter with cron having 7 subexpression

    Unable to use croniter with cron expression have 7 subexpression for e.g. '0 0 0/1 1/1 * ? *'

    can we please support cron expression having 7 subexpression

    opened by sonivi 3
  • `get_next` behaviour seems to have changed in 1.3.0

    `get_next` behaviour seems to have changed in 1.3.0

    Hi, i'm using croniter through Procrastinate, an asynchronous task scheduler and executor. Procrastinate relies on croniter to trigger recurring jobs.

    My recurring jobs have stopped triggering today, and I've pinpointed the issue to this croniter commit: https://github.com/kiorky/croniter/commit/1ea781aa1936214088fa6451c5d62537045869dd

    If I run my procrastinate worker with this croniter version, recurring jobs are not triggered. If I run my procrastinate worker with commit https://github.com/kiorky/croniter/commit/5298c6a3f365503f7c8d25b773d65c2e27b3ac9b (the previous one), everything works as expected.

    Internally, Procrastinate uses the get_next() method to decide how much time to wait before trigerring a recurring job. This is the method that was modified in 1ea781aa1936214088fa6451c5d62537045869dd.

    Do you you think 1ea781aa1936214088fa6451c5d62537045869dd could have introduced a backward incompatible change, or does the issue lies in Procrastinate itself (latest release was on 2021-12-19)?

    opened by agateblue 3
  • Provide option for `.get_next()` and `.get_prev()` to include current

    Provide option for `.get_next()` and `.get_prev()` to include current

    Currently, get_next and get_prev do not account for whether the current time is a match for the cron. They strictly mean next and previous exclusive of the current time -

    >>> from croniter import croniter
    >>> from datetime import datetime
    >>> croniter(" 0 5 * * *", datetime(2020, 1, 1, 5, 0, 0)).get_next(datetime)
    datetime.datetime(2020, 1, 2, 5, 0)
    >>> croniter(" 0 5 * * *", datetime(2020, 1, 1, 5, 0, 0)).get_prev(datetime)
    datetime.datetime(2019, 12, 31, 5, 0)
    

    This is reasonable behaviour but I think it would be better if we can give the users a choice to include the current time as well. So perhaps an extra argument like -

    >>> from croniter import croniter
    >>> from datetime import datetime
    >>> croniter(" 0 5 * * *", datetime(2020, 1, 1, 5, 0, 0)).get_next(datetime, incl_current=True)
    datetime.datetime(2020, 1, 1, 5, 0)
    >>> croniter(" 0 5 * * *", datetime(2020, 1, 1, 5, 0, 0)).get_prev(datetime, incl_current=True)
    datetime.datetime(2020, 1, 1, 5, 0)
    

    I've noticed users subtracting one second from the current time to make it inclusive or using croniter.match with current time first then calling on get_next or get_prev which works but is a bit more verbose. Neither of these options seem very ideal.

    opened by sushinoya 3
  • Fix croniter_range infinite loop

    Fix croniter_range infinite loop

    The issue was caused due to the fact that the result time was adjusted unconditionally though it might have resulted in datetime that does not really exist.

    e.g. If the clock was moved 1 hour forward at March 27 00:00, we do not have that time, but rather March 27 01:00. If we adjust it we get March 26 23:00.

    Closes: #20

    opened by snapiri 2
  • croniter_range may get into infinite loop

    croniter_range may get into infinite loop

    The following code snippet would cause the iter to return the same item over and over:

    import datetime
    
    from croniter import croniter_range
    import pytz
    
    
    mytz = pytz.timezone('Asia/Hebron')
    # Infinite loop
    start_time = mytz.localize(datetime.datetime(2022, 3, 26, 0, 0, 0))
    stop_time = mytz.localize(datetime.datetime(2022, 3, 27, 0, 0, 0))
    ci = croniter_range(start=start_time, stop=stop_time, expr_format="0 0 * * *")
    for item in ci:
        print(f'{item}')
    

    This will result in:

    2022-03-27 00:00:00+03:00
    2022-03-27 00:00:00+03:00
    2022-03-27 00:00:00+03:00
    2022-03-27 00:00:00+03:00
    2022-03-27 00:00:00+03:00
    2022-03-27 00:00:00+03:00
    2022-03-27 00:00:00+03:00
    .
    .
    .
    

    Other timezones that have the same issue (timezone:datetime):

        "America/Asuncion":"2021-10-03 00:00:00-03:00",
        "America/Havana":"2021-03-14 00:00:00-04:00",
        "America/Santiago":"2021-09-05 00:00:00-03:00",
        "America/Scoresbysund":"2021-03-28 00:00:00+00:00",
        "Asia/Amman":"2021-03-26 00:00:00+03:00",
        "Asia/Beirut":"2021-03-28 00:00:00+03:00",
        "Asia/Damascus":"2021-03-26 00:00:00+03:00",
        "Asia/Gaza":"2021-03-27 00:00:00+03:00",
        "Asia/Hebron":"2021-03-27 00:00:00+03:00",
        "Asia/Tehran":"2021-03-22 00:00:00+04:30",
        "Atlantic/Azores":"2021-03-28 00:00:00+00:00",
        "Chile/Continental":"2021-09-05 00:00:00-03:00",
        "Cuba":"2021-03-14 00:00:00-04:00",
        "Iran":"2021-03-22 00:00:00+04:30"
    
    opened by snapiri 2
  • seconds field is conventionally at the front

    seconds field is conventionally at the front

    As far as I gather the seconds field in a cron expression (if it exists at all) is conventionally the first field. This is even described by the Wikipedia article mentioned in the docs. However, for croniter it seems to be the last field instead. Most importantly I think this should be stated explicitly in the docs. Additionally, it would be nice to see it moved to the front, though this would be a breaking change (major version bump?) and it might not be straightforward given how the parsing is currently implemented.

    opened by sanderr 2
  • License info

    License info

    Hello. This isn't really an "issue" but I was wondering if this software has any specific license. I've looked through the repository and didn't seem to find anything.

    Thank you.

    opened by RonsBrain 2
  • Fix #12: `set_current(force=True)` by default

    Fix #12: `set_current(force=True)` by default

    @kiorky I've started a PR that includes a simple test case for this issue and a proposed solution

    The test case fails on master, passes on v1.2.0. As far as I can tell, during https://github.com/kiorky/croniter/commit/1ea781aa1936214088fa6451c5d62537045869dd, the set_current() method signature slightly changed, including an optional force parameter with a default to False.

    When calling set_current(start_time) before get_next(), which Procrastinate does, without specifying force, the set_current() call is basically a no-op, which causes the change of behaviour.

    My suggested fix is to switch the default value for the force argument to True. This fixes the test, restores backward compatibility, and also makes more sense from a UX point of view IMHO: if you're calling set_current() with a non null start_time, you most likely do want it to be used :)

    opened by agateblue 2
  • DST transition behavior

    DST transition behavior

    Running the following code under Python 3.8.10 croniter-1.3.7 Note DST starts at 1 AM on 2022-03-12

    from datetime import datetime from croniter import croniter from dateutil import tz ny = tz.gettz('America/New_York') d1=datetime(2022, 3, 12, 22, 0, 30, tzinfo=ny) it = croniter("0 * * * *", d1) for x in range(0, 10): print(it.get_next(ret_type=datetime))

    I get: 2022-03-12 23:00:00-05:00 2022-03-13 00:00:00-05:00 2022-03-13 01:00:00-05:00 2022-03-13 01:00:00-05:00 2022-03-13 01:00:00-05:00 2022-03-13 01:00:00-05:00 2022-03-13 01:00:00-05:00 2022-03-13 01:00:00-05:00 03-13 01:00:00-05:00 2022-03-13 01:00:00-05:00

    I expected: 2022-03-12 23:00:00-05:00 2022-03-13 00:00:00-05:00 2022-03-13 01:00:00-05:00 2022-03-13 03:00:00-04:00 2022-03-13 04:00:00-04:00 2022-03-13 05:00:00-04:00 2022-03-13 06:00:00-04:00 2022-03-13 07:00:00-04:00 2022-03-13 08:00:00-04:00 2022-03-13 09:00:00-04:00

    opened by garyaviv 1
  • OSS-Fuzz integration for continuous fuzz testing

    OSS-Fuzz integration for continuous fuzz testing

    Hi,

    I was wondering if you would like to integrate continuous fuzzing by way of OSS-Fuzz? Fuzzing is a way to automate test-case generation and has been heavily used for memory unsafe languages. Recently efforts have been put into fuzzing memory safe languages and Python is one of the languages where it would be great to use fuzzing.

    In this PR I did an initial integration into OSS-Fuzz. Essentially, OSS-Fuzz is a free service run by Google that performs continuous fuzzing of important open source projects.

    If you would like to integrate, the only thing I need is a list of email(s) that will get access to the data produced by OSS-Fuzz, such as bug reports, coverage reports and more stats. Notice the emails affiliated with the project will be public in the OSS-Fuzz repo, as they will be part of a configuration file.

    opened by DavidKorczynski 0
  • Croniter mark as valid `10 0 1-5 * 2#2`

    Croniter mark as valid `10 0 1-5 * 2#2`

    The last part #2 is meant to be a comment, this is valid for is_valid

    >>> croniter.is_valid('10 0 1-5 * 2#2')
    True
    

    but later fail is we try to do a next time with:

    >>> from croniter import croniter
    >>> from datetime import datetime
    >>> base = datetime(2010, 1, 25, 4, 46)
    >>> iter = croniter('10 0 1-5 * 2#2', base)
    >>> print(iter.get_next(datetime))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/spk/dev/foundation/testbed/.env/local/lib/python2.7/site-packages/croniter/croniter.py", line 179, in get_next
        return self._get_next(ret_type or self._ret_type, is_prev=False)
      File "/home/spk/dev/foundation/testbed/.env/local/lib/python2.7/site-packages/croniter/croniter.py", line 246, in _get_next
        t1 = self._calc(self.cur, expanded, nth_weekday_of_month, is_prev)
      File "/home/spk/dev/foundation/testbed/.env/local/lib/python2.7/site-packages/croniter/croniter.py", line 527, in _calc
        raise CroniterBadDateError("failed to find next date")
    croniter.croniter.CroniterBadDateError: failed to find next date
    

    Most of the online tools mark this as an error.

    • https://crontab.guru/#10_0_1-5_*_2#2
    • https://freeformatter.com/cron-expression-generator-quartz.html

    Screenshot from 2022-05-18 14-27-32

    Maybe we should mark it invalid directly on is_valid?

    opened by spk 4
  •  Croniter skips 2021-03-01 for

    Croniter skips 2021-03-01 for "0 0 */10 * *" #178

    (originally reported in https://github.com/taichino/croniter/issues/178)

    Test snippet:

    from datetime import datetime
    from croniter import croniter
    
    it = croniter("0 0 */10 * *", datetime(2021, 1, 1))
    
    for i in range(0, 15):
        print(it.get_next(datetime).isoformat())
    

    Result:

    2021-01-11T00:00:00
    2021-01-21T00:00:00
    2021-01-31T00:00:00
    2021-02-01T00:00:00
    2021-02-11T00:00:00
    2021-02-21T00:00:00
    2021-03-11T00:00:00
    2021-03-21T00:00:00
    2021-03-31T00:00:00
    2021-04-01T00:00:00
    2021-04-11T00:00:00
    2021-04-21T00:00:00
    2021-05-01T00:00:00
    2021-05-11T00:00:00
    2021-05-21T00:00:00
    

    In the above output, 2021-03-01T00:00:00 is missing.

    opened by cuu508 3
Owner
kiorky
kiorky
PyTime is an easy-use Python module which aims to operate date/time/datetime by string.

PyTime PyTime is an easy-use Python module which aims to operate date/time/datetime by string. PyTime allows you using nonregular datetime string to g

Sinux 148 Dec 9, 2022
A simple in-process python scheduler library, designed to be integrated seamlessly with the `datetime` standard library.

scheduler A simple in-process python scheduler library, designed to be integrated seamlessly with the datetime standard library. Due to the support of

null 30 Dec 30, 2022
Make Python datetime formatting human readable

Make Python datetime formatting human readable

James Timmins 0 Oct 3, 2021
A datetime parser in Python by Ari24-cb24 and NekoFantic

datetimeparser A datetime parser in Python by Ari24-cb24 and NekoFantic V 1.0 Erinnerung für den Parser Auf falsche Eingaben überprüfen Liste an Event

AriDevelopment 13 Dec 30, 2022
An introduction of Markov decision process (MDP) and two algorithms that solve MDPs (value iteration, policy iteration) along with their Python implementations.

Markov Decision Process A Markov decision process (MDP), by definition, is a sequential decision problem for a fully observable, stochastic environmen

Yu Shen 31 Dec 30, 2022
Django Serverless Cron - Run cron jobs easily in a serverless environment

Django Serverless Cron - Run cron jobs easily in a serverless environment

Paul Onteri 41 Dec 16, 2022
Fully Automated YouTube Channel ▶️with Added Extra Features.

Fully Automated Youtube Channel ▒█▀▀█ █▀▀█ ▀▀█▀▀ ▀▀█▀▀ █░░█ █▀▀▄ █▀▀ █▀▀█ ▒█▀▀▄ █░░█ ░░█░░ ░▒█░░ █░░█ █▀▀▄ █▀▀ █▄▄▀ ▒█▄▄█ ▀▀▀▀ ░░▀░░ ░▒█░░ ░▀▀▀ ▀▀▀░

sam-sepiol 249 Jan 2, 2023
Json2Xml tool will help you convert from json COCO format to VOC xml format in Object Detection Problem.

JSON 2 XML All codes assume running from root directory. Please update the sys path at the beginning of the codes before running. Over View Json2Xml t

Nguyễn Trường Lâu 6 Aug 22, 2022
Txt2Xml tool will help you convert from txt COCO format to VOC xml format in Object Detection Problem.

TXT 2 XML All codes assume running from root directory. Please update the sys path at the beginning of the codes before running. Over View Txt2Xml too

Nguyễn Trường Lâu 4 Nov 24, 2022
A cron monitoring tool written in Python & Django

Healthchecks Healthchecks is a cron job monitoring service. It listens for HTTP requests and email messages ("pings") from your cron jobs and schedule

Healthchecks 5.8k Jan 2, 2023
Another Scheduler is a Kubernetes controller that automatically starts, stops, or restarts pods from a deployment at a specified time using a cron annotation.

Another Scheduler Another Scheduler is a Kubernetes controller that automatically starts, stops, or restarts pods from a deployment at a specified tim

Diego Najar 66 Nov 19, 2022
Another Autoscaler is a Kubernetes controller that automatically starts, stops, or restarts pods from a deployment at a specified time using a cron annotation.

Another Autoscaler Another Autoscaler is a Kubernetes controller that automatically starts, stops, or restarts pods from a deployment at a specified t

Diego Najar 66 Nov 19, 2022
Send e-mails asyncronously using cron

django-yubin Django Yubin allows the programmer to control when he wants to send the e-mail in this application, making the web application to answer

APSL 44 Sep 24, 2022
PyTorch implementation of the Value Iteration Networks (VIN) (NIPS '16 best paper)

Value Iteration Networks in PyTorch Tamar, A., Wu, Y., Thomas, G., Levine, S., and Abbeel, P. Value Iteration Networks. Neural Information Processing

LEI TAI 75 Nov 24, 2022
PyTorch implementation of Value Iteration Networks (VIN): Clean, Simple and Modular. Visualization in Visdom.

VIN: Value Iteration Networks This is an implementation of Value Iteration Networks (VIN) in PyTorch to reproduce the results.(TensorFlow version) Key

Xingdong Zuo 215 Dec 7, 2022
Pytorch implementation of Value Iteration Networks (NIPS 2016 best paper)

VIN: Value Iteration Networks A quick thank you A few others have released amazing related work which helped inspire and improve my own implementation

Kent Sommer 297 Dec 26, 2022
📖 GitHub action schedular (cron) that posts a Hadith every hour on Twitter & Facebook.

Hadith Every Hour ?? A bot that posts a Hadith every hour on Twitter & Facebook (Every 3 hours for now to avoid spamming) Follow on Twitter @HadithEve

Ananto 13 Dec 14, 2022
The code of Zero-shot learning for low-light image enhancement based on dual iteration

Zero-shot-dual-iter-LLE The code of Zero-shot learning for low-light image enhancement based on dual iteration. You can get the real night image tests

null 1 Mar 18, 2022
Useful extensions to the standard Python datetime features

dateutil - powerful extensions to datetime The dateutil module provides powerful extensions to the standard datetime module, available in Python. Inst

null 2k Dec 29, 2022
PyTime is an easy-use Python module which aims to operate date/time/datetime by string.

PyTime PyTime is an easy-use Python module which aims to operate date/time/datetime by string. PyTime allows you using nonregular datetime string to g

Sinux 148 Dec 9, 2022