Hello community,

here is the log from the commit of package python-croniter for openSUSE:Factory 
checked in at 2020-07-17 20:51:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-croniter (Old)
 and      /work/SRC/openSUSE:Factory/.python-croniter.new.3592 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-croniter"

Fri Jul 17 20:51:04 2020 rev:13 rq:821436 version:0.3.34

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-croniter/python-croniter.changes  
2020-06-10 00:47:28.638797561 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-croniter.new.3592/python-croniter.changes    
    2020-07-17 20:51:49.208981002 +0200
@@ -1,0 +2,9 @@
+Fri Jul 17 07:25:05 UTC 2020 - Dirk Mueller <[email protected]>
+
+- update to 0.3.34:
+  - Feat croniter_range(start, stop, cron)
+  - Optimization for poorly written cron expression
+  - Make dateutil tz support more official
+  - Feat/support for day or
+
+-------------------------------------------------------------------

Old:
----
  croniter-0.3.32.tar.gz

New:
----
  croniter-0.3.34.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-croniter.spec ++++++
--- /var/tmp/diff_new_pack.wpQvLS/_old  2020-07-17 20:51:50.368982211 +0200
+++ /var/tmp/diff_new_pack.wpQvLS/_new  2020-07-17 20:51:50.372982216 +0200
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-croniter
-Version:        0.3.32
+Version:        0.3.34
 Release:        0
 Summary:        Python iterators for datetime objects with cron-like format
 License:        MIT

++++++ croniter-0.3.32.tar.gz -> croniter-0.3.34.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/croniter-0.3.32/PKG-INFO new/croniter-0.3.34/PKG-INFO
--- old/croniter-0.3.32/PKG-INFO        2020-05-27 18:01:44.000000000 +0200
+++ new/croniter-0.3.34/PKG-INFO        2020-06-19 15:28:16.774030200 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: croniter
-Version: 0.3.32
+Version: 0.3.34
 Summary: croniter provides iteration for datetime object with cron like format
 Home-page: http://github.com/kiorky/croniter
 Author: Matsumoto Taichi, kiorky
@@ -98,11 +98,23 @@
         
         About DST
         =========
-        Be sure to init your croniter instance with a TZ aware datetime for 
this to work !::
+        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::
@@ -114,18 +126,35 @@
             >>> 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.
+        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 matchs a crontab
         ==================================
-        As simple as::
-         
+        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
+        
+        
+        Iterating over a range using cron
+        =================================
+        Finding all matching times in at time range can be handled with the 
``croniter_range()`` function.  This is much like the builtin 
``range(start,stop,step)`` function, but for dates using a cron expression as 
"step".
+        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)
         
         Develop this package
         ====================
@@ -173,6 +202,22 @@
         Changelog
         ==============
         
+        0.3.34 (2020-06-19)
+        -------------------
+        
+        - Feat croniter_range(start, stop, cron)
+          [Kintyr]
+        - Optimization for poorly written cron expression
+          [Kintyr]
+        
+        0.3.33 (2020-06-15)
+        -------------------
+        
+        - Make dateutil tz support more official
+          [lowell80]
+        - Feat/support for day or
+          [田口信元]
+        
         0.3.32 (2020-05-27)
         -------------------
         
@@ -223,7 +268,7 @@
         0.3.23 (2018-05-23)
         -------------------
         
-        - fix `get_next` while perserving the fix of `get_prev` in 7661c2aaa
+        - fix ``get_next`` while perserving the fix of ``get_prev`` in 
7661c2aaa
           [Avikam Agur <[email protected]>]
         
         
@@ -231,7 +276,7 @@
         -------------------
         - Don't count previous minute if now is dynamic
           If the code is triggered from 5-asterisk based cron
-          `get_prev` based on `datetime.now()` is expected to return
+          ``get_prev`` based on ``datetime.now()`` is expected to return
           current cron iteration and not previous execution.
           [Igor Khrol <[email protected]>]
         
@@ -341,7 +386,7 @@
         ------------------
         
         - Fix default behavior when no start_time given
-          Default value for `start_time` parameter is calculated at module 
init time rather than call time.
+          Default value for ``start_time`` parameter is calculated at module 
init time rather than call time.
         - Fix timezone support and stop depending on the system time zone
         
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/croniter-0.3.32/README.rst 
new/croniter-0.3.34/README.rst
--- old/croniter-0.3.32/README.rst      2020-05-27 18:01:43.000000000 +0200
+++ new/croniter-0.3.34/README.rst      2020-06-19 15:28:16.000000000 +0200
@@ -90,11 +90,23 @@
 
 About DST
 =========
-Be sure to init your croniter instance with a TZ aware datetime for this to 
work !::
+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::
@@ -106,18 +118,35 @@
     >>> 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.
+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 matchs a crontab
 ==================================
-As simple as::
- 
+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
+
+
+Iterating over a range using cron
+=================================
+Finding all matching times in at time range can be handled with the 
``croniter_range()`` function.  This is much like the builtin 
``range(start,stop,step)`` function, but for dates using a cron expression as 
"step".
+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)
 
 Develop this package
 ====================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/croniter-0.3.32/docs/CHANGES.rst 
new/croniter-0.3.34/docs/CHANGES.rst
--- old/croniter-0.3.32/docs/CHANGES.rst        2020-05-27 18:01:43.000000000 
+0200
+++ new/croniter-0.3.34/docs/CHANGES.rst        2020-06-19 15:28:16.000000000 
+0200
@@ -1,6 +1,22 @@
 Changelog
 ==============
 
+0.3.34 (2020-06-19)
+-------------------
+
+- Feat croniter_range(start, stop, cron)
+  [Kintyr]
+- Optimization for poorly written cron expression
+  [Kintyr]
+
+0.3.33 (2020-06-15)
+-------------------
+
+- Make dateutil tz support more official
+  [lowell80]
+- Feat/support for day or
+  [田口信元]
+
 0.3.32 (2020-05-27)
 -------------------
 
@@ -51,7 +67,7 @@
 0.3.23 (2018-05-23)
 -------------------
 
-- fix `get_next` while perserving the fix of `get_prev` in 7661c2aaa
+- fix ``get_next`` while perserving the fix of ``get_prev`` in 7661c2aaa
   [Avikam Agur <[email protected]>]
 
 
@@ -59,7 +75,7 @@
 -------------------
 - Don't count previous minute if now is dynamic
   If the code is triggered from 5-asterisk based cron
-  `get_prev` based on `datetime.now()` is expected to return
+  ``get_prev`` based on ``datetime.now()`` is expected to return
   current cron iteration and not previous execution.
   [Igor Khrol <[email protected]>]
 
@@ -169,7 +185,7 @@
 ------------------
 
 - Fix default behavior when no start_time given
-  Default value for `start_time` parameter is calculated at module init time 
rather than call time.
+  Default value for ``start_time`` parameter is calculated at module init time 
rather than call time.
 - Fix timezone support and stop depending on the system time zone
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/croniter-0.3.32/setup.py new/croniter-0.3.34/setup.py
--- old/croniter-0.3.32/setup.py        2020-05-27 18:01:43.000000000 +0200
+++ new/croniter-0.3.34/setup.py        2020-06-19 15:28:16.000000000 +0200
@@ -23,7 +23,7 @@
 
 setup(
     name='croniter',
-    version='0.3.32',
+    version='0.3.34',
     py_modules=['croniter', ],
     description=(
         'croniter provides iteration for datetime '
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/croniter-0.3.32/src/croniter/__init__.py 
new/croniter-0.3.34/src/croniter/__init__.py
--- old/croniter-0.3.32/src/croniter/__init__.py        2020-05-27 
18:01:43.000000000 +0200
+++ new/croniter-0.3.34/src/croniter/__init__.py        2020-06-19 
15:28:16.000000000 +0200
@@ -2,6 +2,7 @@
 from __future__ import absolute_import
 from .croniter import (
     croniter,
+    croniter_range,
     CroniterBadDateError,  # noqa
     CroniterBadCronError,  # noqa
     CroniterNotAlphaError  # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/croniter-0.3.32/src/croniter/croniter.py 
new/croniter-0.3.34/src/croniter/croniter.py
--- old/croniter-0.3.32/src/croniter/croniter.py        2020-05-27 
18:01:43.000000000 +0200
+++ new/croniter-0.3.34/src/croniter/croniter.py        2020-06-19 
15:28:16.000000000 +0200
@@ -69,6 +69,15 @@
         {},
     )
 
+    LEN_MEANS_ALL = (
+        60,
+        24,
+        31,
+        12,
+        7,
+        60
+    )
+
     bad_length = 'Exactly 5 or 6 columns has to be specified for iterator' \
                  'expression.'
 
@@ -569,7 +578,11 @@
                             nth_weekday_of_month[t] = set()
                         nth_weekday_of_month[t].add(int(nth))
 
+            res = set(res)
             res = natsort.natsorted(res)
+            if len(res) == cls.LEN_MEANS_ALL[i]:
+                res = ['*']
+
             expanded.append(['*'] if (len(res) == 1
                                       and res[0] == '*')
                             else res)
@@ -586,9 +599,55 @@
             return True
 
     @classmethod
-    def match(cls, cron_expression, testdate):
-        cron = cls(cron_expression, testdate, ret_type=datetime.datetime)
+    def match(cls, cron_expression, testdate, day_or=True):
+        cron = cls(cron_expression, testdate, ret_type=datetime.datetime, 
day_or=day_or)
         td, ms1 = cron.get_current(datetime.datetime), 
relativedelta(microseconds=1)
         cron.set_current(td + ms1)
         tdp, tdt = cron.get_current(), cron.get_prev()
         return (max(tdp, tdt) - min(tdp, tdt)).total_seconds() < 60
+
+
+def croniter_range(start, stop, expr_format, ret_type=None, day_or=True, 
exclude_ends=False):
+    """
+    Generator that provides all times from start to stop matching the given 
cron expression.
+    If the cron expression matches either 'start' and/or 'stop', those times 
will be returned as
+    well unless 'exclude_ends=True' is passed.
+
+    You can think of this function as sibling to the builtin range function 
for datetime objects.
+    Like range(start,stop,step), except that here 'step' is a cron expression.
+    """
+    auto_rt = datetime.datetime
+    if type(start) != type(stop):
+        raise TypeError("The start and stop must be same type.  {0} != {1}".
+                        format(type(start), type(stop)))
+    if isinstance(start, (float, int)):
+        start, stop = (datetime.datetime.utcfromtimestamp(t) for t in (start, 
stop))
+        auto_rt = float
+    if ret_type is None:
+        ret_type = auto_rt
+    if not exclude_ends:
+        ms1 = relativedelta(microseconds=1)
+        if start < stop:    # Forward (normal) time order
+            start -= ms1
+            stop += ms1
+        else:               # Reverse time order
+            start += ms1
+            stop -= ms1
+    ic = croniter(expr_format, start, ret_type=datetime.datetime, 
day_or=day_or)
+    # define a continue (cont) condition function and step function for the 
main while loop
+    if start < stop:        # Forward
+        def cont(v):
+            return v < stop
+        step = ic.get_next
+    else:                   # Reverse
+        def cont(v):
+            return v > stop
+        step = ic.get_prev
+
+    dt = step()
+    while cont(dt):
+        if ret_type is float:
+            yield ic.get_current(float)
+        else:
+            yield dt
+        dt = step()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/croniter-0.3.32/src/croniter/tests/test_croniter.py 
new/croniter-0.3.34/src/croniter/tests/test_croniter.py
--- old/croniter-0.3.32/src/croniter/tests/test_croniter.py     2020-05-27 
18:01:43.000000000 +0200
+++ new/croniter-0.3.34/src/croniter/tests/test_croniter.py     2020-06-19 
15:28:16.000000000 +0200
@@ -6,9 +6,10 @@
 from functools import partial
 from time import sleep
 import pytz
-from croniter import croniter, CroniterBadDateError, CroniterBadCronError, 
CroniterNotAlphaError
+from croniter import croniter, croniter_range, CroniterBadDateError, 
CroniterBadCronError, CroniterNotAlphaError
 from croniter.tests import base
 from tzlocal import get_localzone
+import dateutil.tz
 
 
 class CroniterTest(base.TestCase):
@@ -298,6 +299,32 @@
         self.assertEqual(22, next.hour)
         self.assertEqual(30, next.minute)
 
+    def testOptimizeCronExpressions(self):
+        """ Non-optimal cron expressions that can be simplified."""
+        wildcard = ['*']
+        m, h, d, mon, dow, s = range(6)
+        # Test each field individually 
+        self.assertEqual(croniter('0-59 0 0 0 0').expanded[m], wildcard)
+        self.assertEqual(croniter('0 0-23 0 0 0').expanded[h], wildcard)
+        self.assertEqual(croniter('0 0 0-31 0 0').expanded[d], wildcard)
+        self.assertEqual(croniter('0 0 0 1-12 0').expanded[mon], wildcard)
+        self.assertEqual(croniter('0 0 0 0 0-6').expanded[dow], wildcard)
+        self.assertEqual(croniter('0 0 0 0 1-7').expanded[dow], wildcard)
+        self.assertEqual(croniter('0 0 0 0 0 0-59').expanded[s], wildcard)
+        # Real life examples
+        self.assertEqual(croniter('30 1-12,0,10-23 15-21 * fri').expanded[h], 
wildcard)
+        self.assertEqual(croniter('30 1-23,0 15-21 * fri').expanded[h], 
wildcard)
+
+    def testBlockDupRanges(self):
+        """ Ensure that duplicate/overlapping ranges are squashed """
+        m, h, d, mon, dow, s = range(6)
+        self.assertEqual(croniter('* 5,5,1-6 * * *').expanded[h], 
[1,2,3,4,5,6])
+        self.assertEqual(croniter('* * * * 2-3,4-5,3,3,3').expanded[dow], 
[2,3,4,5])
+        self.assertEqual(croniter('* * * * * 1,5,*/20,20,15').expanded[s], [0, 
1, 5, 15, 20, 40])
+        self.assertEqual(croniter('* 4,1-4,5,4 * * *').expanded[h], [1, 2, 3, 
4, 5])
+        # Real life example
+        self.assertEqual(croniter('59 23 * 1 
wed,fri,mon-thu,tue,tue').expanded[dow], [1,2,3,4,5])
+
     def testPrevMinute(self):
         base = datetime(2010, 8, 25, 15, 56)
         itr = croniter('*/1 * * * *', base)
@@ -650,6 +677,13 @@
         n2 = itr2.get_next(datetime)
         self.assertEqual(n2.tzinfo.zone, 'Asia/Tokyo')
 
+    def testTimezoneDateutil(self):
+        tokyo = dateutil.tz.gettz('Asia/Tokyo')
+        base = datetime(2013, 3, 4, 12, 15, tzinfo=tokyo)
+        itr = croniter('* * * * *', base)
+        n1 = itr.get_next(datetime)
+        self.assertEqual(n1.tzinfo.tzname(n1), 'JST')
+
     def testInitNoStartTime(self):
         itr = croniter('* * * * *')
         sleep(.01)
@@ -970,6 +1004,36 @@
             "31 * * * *",
             datetime(2019, 1, 14, 1, 31, 0, 0)
         ))
+        self.assertTrue(croniter.match(
+            "0 0 10 * wed",
+            datetime(2020, 6, 10, 0, 0, 0, 0),
+            day_or=True
+        ))
+        self.assertTrue(croniter.match(
+            "0 0 10 * fri",
+            datetime(2020, 6, 10, 0, 0, 0, 0),
+            day_or=True
+        ))
+        self.assertTrue(croniter.match(
+            "0 0 10 * fri",
+            datetime(2020, 6, 12, 0, 0, 0, 0),
+            day_or=True
+        ))
+        self.assertTrue(croniter.match(
+            "0 0 10 * wed",
+            datetime(2020, 6, 10, 0, 0, 0, 0),
+            day_or=False
+        ))
+        self.assertFalse(croniter.match(
+            "0 0 10 * fri",
+            datetime(2020, 6, 10, 0, 0, 0, 0),
+            day_or=False
+        ))
+        self.assertFalse(croniter.match(
+            "0 0 10 * fri",
+            datetime(2020, 6, 12, 0, 0, 0, 0),
+            day_or=False
+        ))
 
 
     def test_dst_issue90_st31ny(self):
@@ -1018,12 +1082,106 @@
             itt.get_next(datetime).isoformat(),
             itt.get_next(datetime).isoformat(),
         ]
-        self.assertEqual(ret, [
+        self.assertEqual(rett, [
             '2020-03-30T02:01:00+02:00',
             '2020-03-29T01:01:00+01:00',
             '2020-03-28T03:01:00+01:00',
             '2020-03-29T02:01:00+02:00',
             '2020-03-29T03:01:00+02:00'])
 
+
+class CroniterRangeTest(base.TestCase):
+
+    def test_1day_step(self):
+        start = datetime(2016, 12, 2)
+        stop = datetime(2016, 12, 10)
+        fwd = list(croniter_range(start, stop, '0 0 * * *'))
+        self.assertEqual(len(fwd), 9)
+        self.assertEqual(fwd[0], start)
+        self.assertEqual(fwd[-1], stop)
+        # Test the same, but in reverse
+        rev = list(croniter_range(stop, start, '0 0 * * *'))
+        self.assertEqual(len(rev), 9)
+        # Ensure forward/reverse are a mirror image
+        rev.reverse()
+        self.assertEqual(fwd, rev)
+
+    def test_1day_step_no_ends(self):
+        # Test without ends (exclusive)
+        start = datetime(2016, 12, 2)
+        stop = datetime(2016, 12, 10)
+        fwd = list(croniter_range(start, stop, '0 0 * * *', exclude_ends=True))
+        self.assertEqual(len(fwd), 7)
+        self.assertNotEqual(fwd[0], start)
+        self.assertNotEqual(fwd[-1], stop)
+        # Test the same, but in reverse
+        rev = list(croniter_range(stop, start, '0 0 * * *', exclude_ends=True))
+        self.assertEqual(len(rev), 7)
+        self.assertNotEqual(fwd[0], stop)
+        self.assertNotEqual(fwd[-1], start)
+
+    def test_1month_step(self):
+        start = datetime(1982, 1, 1)
+        stop = datetime(1983, 12, 31)
+        res = list(croniter_range(start, stop, '0 0 1 * *'))
+        self.assertEqual(len(res), 24)
+        self.assertEqual(res[0], start)
+        self.assertEqual(res[5].day, 1)
+        self.assertEqual(res[-1], datetime(1983, 12, 1))
+
+    def test_1minute_step_float(self):
+        start = datetime(2000, 1, 1, 0, 0)
+        stop =  datetime(2000, 1, 1, 0, 1)
+        res = list(croniter_range(start, stop, '* * * * *', ret_type=float))
+        self.assertEqual(len(res), 2)
+        self.assertEqual(res[0], 946684800.0)
+        self.assertEqual(res[-1] - res[0], 60)
+
+    def test_auto_ret_type(self):
+        data = [
+            (datetime(2019, 1, 1), datetime(2020, 1, 1), datetime),
+            (1552252218.0, 1591823311.0, float),
+        ]
+        for start, stop, rtype in data:
+            ret = list(croniter_range(start, stop, "0 0 * * *"))
+            self.assertIsInstance(ret[0], rtype)
+
+    def test_input_type_exceptions(self):
+        dt_start1 = datetime(2019, 1, 1)
+        dt_stop1 = datetime(2020, 1, 1)
+        f_start1 = 1552252218.0
+        f_stop1 = 1591823311.0
+        # Mix start/stop types
+        with self.assertRaises(TypeError):
+            list(croniter_range(dt_start1, f_stop1, "0 * * * *"), 
ret_type=datetime)
+        with self.assertRaises(TypeError):
+            list(croniter_range(f_start1, dt_stop1, "0 * * * *"))
+
+    def test_timezone_dst(self):
+        """ Test across DST transition, which technially is a timzone change. 
"""
+        tz = pytz.timezone("US/Eastern")
+        start = tz.localize(datetime(2020, 10, 30))
+        stop =  tz.localize(datetime(2020, 11, 10))
+        res = list(croniter_range(start, stop, '0 0 * * *'))
+        self.assertNotEqual(res[0].tzinfo, res[-1].tzinfo)
+        self.assertEqual(len(res), 12)
+
+    def test_extra_hour_day_prio(self):
+        def datetime_tz(*args, **kw):
+            """ Defined this in another branch.  single-use-version """
+            tzinfo = kw.pop("tzinfo")
+            return tzinfo.localize(datetime(*args))
+        tz = pytz.timezone("US/Eastern")
+        cron = "0 3 * * *"
+        start = datetime_tz(2020, 3, 7, tzinfo=tz)
+        end = datetime_tz(2020, 3, 11, tzinfo=tz)
+        ret = [ i.isoformat() for i in croniter_range(start, end, cron) ]
+        self.assertEqual(ret, [
+            "2020-03-07T03:00:00-05:00",
+            "2020-03-08T03:00:00-04:00",
+            "2020-03-09T03:00:00-04:00",
+            "2020-03-10T03:00:00-04:00"])
+
+
 if __name__ == '__main__':
     unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/croniter-0.3.32/src/croniter.egg-info/PKG-INFO 
new/croniter-0.3.34/src/croniter.egg-info/PKG-INFO
--- old/croniter-0.3.32/src/croniter.egg-info/PKG-INFO  2020-05-27 
18:01:44.000000000 +0200
+++ new/croniter-0.3.34/src/croniter.egg-info/PKG-INFO  2020-06-19 
15:28:16.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: croniter
-Version: 0.3.32
+Version: 0.3.34
 Summary: croniter provides iteration for datetime object with cron like format
 Home-page: http://github.com/kiorky/croniter
 Author: Matsumoto Taichi, kiorky
@@ -98,11 +98,23 @@
         
         About DST
         =========
-        Be sure to init your croniter instance with a TZ aware datetime for 
this to work !::
+        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::
@@ -114,18 +126,35 @@
             >>> 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.
+        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 matchs a crontab
         ==================================
-        As simple as::
-         
+        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
+        
+        
+        Iterating over a range using cron
+        =================================
+        Finding all matching times in at time range can be handled with the 
``croniter_range()`` function.  This is much like the builtin 
``range(start,stop,step)`` function, but for dates using a cron expression as 
"step".
+        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)
         
         Develop this package
         ====================
@@ -173,6 +202,22 @@
         Changelog
         ==============
         
+        0.3.34 (2020-06-19)
+        -------------------
+        
+        - Feat croniter_range(start, stop, cron)
+          [Kintyr]
+        - Optimization for poorly written cron expression
+          [Kintyr]
+        
+        0.3.33 (2020-06-15)
+        -------------------
+        
+        - Make dateutil tz support more official
+          [lowell80]
+        - Feat/support for day or
+          [田口信元]
+        
         0.3.32 (2020-05-27)
         -------------------
         
@@ -223,7 +268,7 @@
         0.3.23 (2018-05-23)
         -------------------
         
-        - fix `get_next` while perserving the fix of `get_prev` in 7661c2aaa
+        - fix ``get_next`` while perserving the fix of ``get_prev`` in 
7661c2aaa
           [Avikam Agur <[email protected]>]
         
         
@@ -231,7 +276,7 @@
         -------------------
         - Don't count previous minute if now is dynamic
           If the code is triggered from 5-asterisk based cron
-          `get_prev` based on `datetime.now()` is expected to return
+          ``get_prev`` based on ``datetime.now()`` is expected to return
           current cron iteration and not previous execution.
           [Igor Khrol <[email protected]>]
         
@@ -341,7 +386,7 @@
         ------------------
         
         - Fix default behavior when no start_time given
-          Default value for `start_time` parameter is calculated at module 
init time rather than call time.
+          Default value for ``start_time`` parameter is calculated at module 
init time rather than call time.
         - Fix timezone support and stop depending on the system time zone
         
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/croniter-0.3.32/src/croniter.egg-info/requires.txt 
new/croniter-0.3.34/src/croniter.egg-info/requires.txt
--- old/croniter-0.3.32/src/croniter.egg-info/requires.txt      2020-05-27 
18:01:44.000000000 +0200
+++ new/croniter-0.3.34/src/croniter.egg-info/requires.txt      2020-06-19 
15:28:16.000000000 +0200
@@ -1,2 +1,2 @@
-python_dateutil
 natsort
+python_dateutil


Reply via email to