opendate 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of opendate might be problematic. Click here for more details.

date/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = '0.1.2'
1
+ __version__ = '0.1.4'
2
2
 
3
3
  import datetime as _datetime
4
4
 
@@ -31,7 +31,9 @@ from date.date import expect_utc_timezone
31
31
  from date.date import prefer_native_timezone
32
32
  from date.date import prefer_utc_timezone
33
33
  from date.date import Timezone
34
- from date.business import *
34
+ from date.extras import overlap_days
35
+ from date.extras import is_business_day
36
+ from date.extras import is_within_business_hours
35
37
 
36
38
 
37
39
  timezone = Timezone
@@ -49,16 +51,14 @@ def time(*args, **kwargs):
49
51
  return Time(*args, **kwargs)
50
52
 
51
53
 
52
- def parse():
53
- """Generic parser that guesses type"""
54
- raise NotImplementedError(
55
- 'Generic parser not implemented, use Date or DateTime parsers'
56
- )
54
+ def parse(s: str | None, fmt: str = None, entity: Entity = NYSE, raise_err: bool = False) -> DateTime | None:
55
+ """Parse using DateTime.parse
56
+ """
57
+ return DateTime.parse(s, entity=entity, raise_err=True)
57
58
 
58
59
 
59
60
  def instance(obj: _datetime.date | _datetime.datetime | _datetime.time) -> DateTime | Date | Time:
60
- """
61
- Create a DateTime/Date/Time instance from a datetime/date/time native one.
61
+ """Create a DateTime/Date/Time instance from a datetime/date/time native one.
62
62
  """
63
63
  if isinstance(obj, DateTime | Date | Time):
64
64
  return obj
@@ -71,13 +71,13 @@ def instance(obj: _datetime.date | _datetime.datetime | _datetime.time) -> DateT
71
71
 
72
72
 
73
73
  def now(tz: str | _zoneinfo.ZoneInfo | None = None) -> DateTime:
74
- """Get current datetime
74
+ """Returns Datetime.now
75
75
  """
76
76
  return DateTime.now(tz)
77
77
 
78
78
 
79
79
  def today(tz: str | _zoneinfo.ZoneInfo = None) -> DateTime:
80
- """Get current date
80
+ """Returns DateTime.today
81
81
  """
82
82
  return DateTime.today(tz)
83
83
 
@@ -104,6 +104,8 @@ __all__ = [
104
104
  'NYSE',
105
105
  'date',
106
106
  'datetime',
107
- 'time'
108
- 'within_business_hours'
107
+ 'time',
108
+ 'overlap_days',
109
+ 'is_within_business_hours',
110
+ 'is_business_day',
109
111
  ]
date/date.py CHANGED
@@ -8,9 +8,7 @@ import time
8
8
  import warnings
9
9
  import zoneinfo as _zoneinfo
10
10
  from abc import ABC, abstractmethod
11
- from collections import namedtuple
12
11
  from collections.abc import Callable, Sequence
13
- from enum import IntEnum
14
12
  from functools import lru_cache, partial, wraps
15
13
  from typing import Self
16
14
 
@@ -31,8 +29,6 @@ __all__ = [
31
29
  'IntervalError',
32
30
  'Time',
33
31
  'Timezone',
34
- 'WeekDay',
35
- 'WEEKDAY_SHORTNAME',
36
32
  'EST',
37
33
  'UTC',
38
34
  'GMT',
@@ -45,11 +41,33 @@ __all__ = [
45
41
  'expect_datetime',
46
42
  'Entity',
47
43
  'NYSE'
44
+ 'WEEKDAY_SHORTNAME',
48
45
  ]
49
46
 
50
47
 
51
48
  def Timezone(name:str = 'US/Eastern') -> _zoneinfo.ZoneInfo:
52
49
  """Simple wrapper around Pendulum `Timezone`
50
+
51
+ Ex: sanity check US/Eastern == America/New_York
52
+
53
+ >>> winter1 = DateTime(2000, 1, 1, 12, tzinfo=Timezone('US/Eastern'))
54
+ >>> winter2 = DateTime(2000, 1, 1, 12, tzinfo=Timezone('America/New_York'))
55
+
56
+ >>> summer1 = DateTime(2000, 7, 1, 12, tzinfo=Timezone('US/Eastern'))
57
+ >>> summer2 = DateTime(2000, 7, 1, 12, tzinfo=Timezone('America/New_York'))
58
+
59
+ >>> winter = [winter1, winter2,
60
+ ... winter1.astimezone(Timezone('America/New_York')),
61
+ ... winter2.astimezone(Timezone('US/Eastern')),
62
+ ... ]
63
+ >>> assert all(x==winter[0] for x in winter)
64
+
65
+ >>> summer = [summer1, summer2,
66
+ ... summer1.astimezone(Timezone('America/New_York')),
67
+ ... summer2.astimezone(Timezone('US/Eastern')),
68
+ ... ]
69
+ >>> assert all(x==summer[0] for x in summer)
70
+
53
71
  """
54
72
  return _pendulum.tz.Timezone(name)
55
73
 
@@ -59,16 +77,7 @@ GMT = Timezone('GMT')
59
77
  EST = Timezone('US/Eastern')
60
78
  LCL = _pendulum.tz.Timezone(_pendulum.tz.get_local_timezone().name)
61
79
 
62
-
63
- class WeekDay(IntEnum):
64
- MONDAY = 0
65
- TUESDAY = 1
66
- WEDNESDAY = 2
67
- THURSDAY = 3
68
- FRIDAY = 4
69
- SATURDAY = 5
70
- SUNDAY = 6
71
-
80
+ WeekDay = _pendulum.day.WeekDay
72
81
 
73
82
  WEEKDAY_SHORTNAME = {
74
83
  'MO': WeekDay.MONDAY,
@@ -281,7 +290,7 @@ class NYSE(Entity):
281
290
  if begdate <= d <= enddate}
282
291
 
283
292
 
284
- class PendulumBusinessDateMixin:
293
+ class DateBusinessMixin:
285
294
 
286
295
  _entity: type[NYSE] = NYSE
287
296
  _business: bool = False
@@ -509,7 +518,141 @@ class PendulumBusinessDateMixin:
509
518
  return self
510
519
 
511
520
 
512
- class Date(PendulumBusinessDateMixin, _pendulum.Date):
521
+ class DateExtrasMixin:
522
+ """Legacy support functionality well outside the
523
+ scope of Pendulum. Ideally these should be removed.
524
+
525
+ See how pendulum does end_of and next_ with getattr
526
+
527
+ Create a nearest [start_of, end_of] [week, day, month, quarter, year]
528
+
529
+ combo that accounts for whatever prefix and unit is passed in
530
+ """
531
+
532
+ def nearest_start_of_month(self):
533
+ """Get `nearest` start of month
534
+
535
+ 1/1/2015 -> Thursday (New Year's Day)
536
+ 2/1/2015 -> Sunday
537
+
538
+ >>> from date import Date
539
+ >>> Date(2015, 1, 1).nearest_start_of_month()
540
+ Date(2015, 1, 1)
541
+ >>> Date(2015, 1, 15).nearest_start_of_month()
542
+ Date(2015, 1, 1)
543
+ >>> Date(2015, 1, 15).b.nearest_start_of_month()
544
+ Date(2015, 1, 2)
545
+ >>> Date(2015, 1, 16).nearest_start_of_month()
546
+ Date(2015, 2, 1)
547
+ >>> Date(2015, 1, 31).nearest_start_of_month()
548
+ Date(2015, 2, 1)
549
+ >>> Date(2015, 1, 31).b.nearest_start_of_month()
550
+ Date(2015, 2, 2)
551
+ """
552
+ _business = self._business
553
+ self._business = False
554
+ if self.day > 15:
555
+ d = self.end_of('month')
556
+ if _business:
557
+ return d.business().add(days=1)
558
+ return d.add(days=1)
559
+ d = self.start_of('month')
560
+ if _business:
561
+ return d.business().add(days=1)
562
+ return d
563
+
564
+ def nearest_end_of_month(self):
565
+ """Get `nearest` end of month
566
+
567
+ 12/31/2014 -> Wednesday
568
+ 1/31/2015 -> Saturday
569
+
570
+ >>> from date import Date
571
+ >>> Date(2015, 1, 1).nearest_end_of_month()
572
+ Date(2014, 12, 31)
573
+ >>> Date(2015, 1, 15).nearest_end_of_month()
574
+ Date(2014, 12, 31)
575
+ >>> Date(2015, 1, 15).b.nearest_end_of_month()
576
+ Date(2014, 12, 31)
577
+ >>> Date(2015, 1, 16).nearest_end_of_month()
578
+ Date(2015, 1, 31)
579
+ >>> Date(2015, 1, 31).nearest_end_of_month()
580
+ Date(2015, 1, 31)
581
+ >>> Date(2015, 1, 31).b.nearest_end_of_month()
582
+ Date(2015, 1, 30)
583
+ """
584
+ _business = self._business
585
+ self._business = False
586
+ if self.day <= 15:
587
+ d = self.start_of('month')
588
+ if _business:
589
+ return d.business().subtract(days=1)
590
+ return d.subtract(days=1)
591
+ d = self.end_of('month')
592
+ if _business:
593
+ return d.business().subtract(days=1)
594
+ return d
595
+
596
+ def next_relative_date_of_week_by_day(self, day='MO'):
597
+ """Get next relative day of week by relativedelta code
598
+
599
+ >>> from date import Date
600
+ >>> Date(2020, 5, 18).next_relative_date_of_week_by_day('SU')
601
+ Date(2020, 5, 24)
602
+ >>> Date(2020, 5, 24).next_relative_date_of_week_by_day('SU')
603
+ Date(2020, 5, 24)
604
+ """
605
+ if self.weekday() == WEEKDAY_SHORTNAME.get(day):
606
+ return self
607
+ return self.next(WEEKDAY_SHORTNAME.get(day))
608
+
609
+ def weekday_or_previous_friday(self):
610
+ """Return the date if it is a weekday, else previous Friday
611
+
612
+ >>> from date import Date
613
+ >>> Date(2019, 10, 6).weekday_or_previous_friday() # Sunday
614
+ Date(2019, 10, 4)
615
+ >>> Date(2019, 10, 5).weekday_or_previous_friday() # Saturday
616
+ Date(2019, 10, 4)
617
+ >>> Date(2019, 10, 4).weekday_or_previous_friday() # Friday
618
+ Date(2019, 10, 4)
619
+ >>> Date(2019, 10, 3).weekday_or_previous_friday() # Thursday
620
+ Date(2019, 10, 3)
621
+ """
622
+ dnum = self.weekday()
623
+ if dnum in {WeekDay.SATURDAY, WeekDay.SUNDAY}:
624
+ return self.subtract(days=dnum - 4)
625
+ return self
626
+
627
+ """
628
+ create a simple nth weekday function that accounts for
629
+ [1,2,3,4] and weekday as options
630
+ or weekday, [1,2,3,4]
631
+
632
+ """
633
+
634
+ @classmethod
635
+ def third_wednesday(cls, year, month):
636
+ """Third Wednesday date of a given month/year
637
+
638
+ >>> from date import Date
639
+ >>> Date.third_wednesday(2022, 6)
640
+ Date(2022, 6, 15)
641
+ >>> Date.third_wednesday(2023, 3)
642
+ Date(2023, 3, 15)
643
+ >>> Date.third_wednesday(2022, 12)
644
+ Date(2022, 12, 21)
645
+ >>> Date.third_wednesday(2023, 6)
646
+ Date(2023, 6, 21)
647
+ """
648
+ third = cls(year, month, 15) # lowest 3rd day
649
+ w = third.weekday()
650
+ if w != WeekDay.WEDNESDAY:
651
+ third = third.replace(day=(15 + (WeekDay.WEDNESDAY - w) % 7))
652
+ return third
653
+
654
+
655
+ class Date(DateExtrasMixin, DateBusinessMixin, _pendulum.Date):
513
656
  """Inherits and wraps pendulum.Date
514
657
  """
515
658
 
@@ -768,105 +911,6 @@ class Date(PendulumBusinessDateMixin, _pendulum.Date):
768
911
  with contextlib.suppress(Exception):
769
912
  return self.isocalendar()[1]
770
913
 
771
- """
772
- See how pendulum does end_of and next_ with getattr
773
-
774
- Create a nearest [start_of, end_of] [week, day, month, quarter, year]
775
-
776
- combo that accounts for whatever prefix and unit is passed in
777
- """
778
-
779
- def nearest_start_of_month(self):
780
- """Get `nearest` start of month
781
-
782
- 1/1/2015 -> Thursday (New Year's Day)
783
- 2/1/2015 -> Sunday
784
-
785
- >>> Date(2015, 1, 1).nearest_start_of_month()
786
- Date(2015, 1, 1)
787
- >>> Date(2015, 1, 15).nearest_start_of_month()
788
- Date(2015, 1, 1)
789
- >>> Date(2015, 1, 15).b.nearest_start_of_month()
790
- Date(2015, 1, 2)
791
- >>> Date(2015, 1, 16).nearest_start_of_month()
792
- Date(2015, 2, 1)
793
- >>> Date(2015, 1, 31).nearest_start_of_month()
794
- Date(2015, 2, 1)
795
- >>> Date(2015, 1, 31).b.nearest_start_of_month()
796
- Date(2015, 2, 2)
797
- """
798
- _business = self._business
799
- self._business = False
800
- if self.day > 15:
801
- d = self.end_of('month')
802
- if _business:
803
- return d.business().add(days=1)
804
- return d.add(days=1)
805
- d = self.start_of('month')
806
- if _business:
807
- return d.business().add(days=1)
808
- return d
809
-
810
- def nearest_end_of_month(self):
811
- """Get `nearest` end of month
812
-
813
- 12/31/2014 -> Wednesday
814
- 1/31/2015 -> Saturday
815
-
816
- >>> Date(2015, 1, 1).nearest_end_of_month()
817
- Date(2014, 12, 31)
818
- >>> Date(2015, 1, 15).nearest_end_of_month()
819
- Date(2014, 12, 31)
820
- >>> Date(2015, 1, 15).b.nearest_end_of_month()
821
- Date(2014, 12, 31)
822
- >>> Date(2015, 1, 16).nearest_end_of_month()
823
- Date(2015, 1, 31)
824
- >>> Date(2015, 1, 31).nearest_end_of_month()
825
- Date(2015, 1, 31)
826
- >>> Date(2015, 1, 31).b.nearest_end_of_month()
827
- Date(2015, 1, 30)
828
- """
829
- _business = self._business
830
- self._business = False
831
- if self.day <= 15:
832
- d = self.start_of('month')
833
- if _business:
834
- return d.business().subtract(days=1)
835
- return d.subtract(days=1)
836
- d = self.end_of('month')
837
- if _business:
838
- return d.business().subtract(days=1)
839
- return d
840
-
841
- def next_relative_date_of_week_by_day(self, day='MO'):
842
- """Get next relative day of week by relativedelta code
843
-
844
- >>> Date(2020, 5, 18).next_relative_date_of_week_by_day('SU')
845
- Date(2020, 5, 24)
846
- >>> Date(2020, 5, 24).next_relative_date_of_week_by_day('SU')
847
- Date(2020, 5, 24)
848
- """
849
- if self.weekday() == WEEKDAY_SHORTNAME.get(day):
850
- return self
851
- return self.next(WEEKDAY_SHORTNAME.get(day))
852
-
853
- def weekday_or_previous_friday(self):
854
- """Return the date if it is a weekday, else previous Friday
855
-
856
- >>> Date(2019, 10, 6).weekday_or_previous_friday() # Sunday
857
- Date(2019, 10, 4)
858
- >>> Date(2019, 10, 5).weekday_or_previous_friday() # Saturday
859
- Date(2019, 10, 4)
860
- >>> Date(2019, 10, 4).weekday_or_previous_friday() # Friday
861
- Date(2019, 10, 4)
862
- >>> Date(2019, 10, 3).weekday_or_previous_friday() # Thursday
863
- Date(2019, 10, 3)
864
- """
865
- dnum = self.weekday()
866
- if dnum in {WeekDay.SATURDAY, WeekDay.SUNDAY}:
867
- return self.subtract(days=dnum - 4)
868
- return self
869
-
870
914
  def lookback(self, unit='last') -> Self:
871
915
  """Date back based on lookback string, ie last, week, month.
872
916
 
@@ -897,32 +941,6 @@ class Date(PendulumBusinessDateMixin, _pendulum.Date):
897
941
  'year': _lookback(years=1),
898
942
  }.get(unit)
899
943
 
900
- """
901
- create a simple nth weekday function that accounts for
902
- [1,2,3,4] and weekday as options
903
- or weekday, [1,2,3,4]
904
-
905
- """
906
-
907
- @staticmethod
908
- def third_wednesday(year, month):
909
- """Third Wednesday date of a given month/year
910
-
911
- >>> Date.third_wednesday(2022, 6)
912
- Date(2022, 6, 15)
913
- >>> Date.third_wednesday(2023, 3)
914
- Date(2023, 3, 15)
915
- >>> Date.third_wednesday(2022, 12)
916
- Date(2022, 12, 21)
917
- >>> Date.third_wednesday(2023, 6)
918
- Date(2023, 6, 21)
919
- """
920
- third = Date(year, month, 15) # lowest 3rd day
921
- w = third.weekday()
922
- if w != WeekDay.WEDNESDAY:
923
- third = third.replace(day=(15 + (WeekDay.WEDNESDAY - w) % 7))
924
- return third
925
-
926
944
 
927
945
  class Time(_pendulum.Time):
928
946
 
@@ -1050,7 +1068,7 @@ class Time(_pendulum.Time):
1050
1068
  tzinfo=obj.tzinfo or tz)
1051
1069
 
1052
1070
 
1053
- class DateTime(PendulumBusinessDateMixin, _pendulum.DateTime):
1071
+ class DateTime(DateBusinessMixin, _pendulum.DateTime):
1054
1072
  """Inherits and wraps pendulum.DateTime
1055
1073
  """
1056
1074
 
@@ -1118,7 +1136,11 @@ class DateTime(PendulumBusinessDateMixin, _pendulum.DateTime):
1118
1136
  return Time.instance(self)
1119
1137
 
1120
1138
  @classmethod
1121
- def parse(cls, s: str | int | None, raise_err: bool = False) -> Self | None:
1139
+ def parse(
1140
+ cls, s: str | int | None,
1141
+ entity: Entity = NYSE,
1142
+ raise_err: bool = False
1143
+ ) -> Self | None:
1122
1144
  """Thin layer on Date parser and our custom `Date.parse``
1123
1145
 
1124
1146
  >>> DateTime.parse('2022/1/1')
@@ -1176,7 +1198,7 @@ class DateTime(PendulumBusinessDateMixin, _pendulum.DateTime):
1176
1198
  if d is not None and t is not None:
1177
1199
  return DateTime.combine(d, t, LCL)
1178
1200
 
1179
- d = Date.parse(s)
1201
+ d = Date.parse(s, entity=entity)
1180
1202
  if d is not None:
1181
1203
  return cls(d.year, d.month, d.day, 0, 0, 0)
1182
1204
 
@@ -1613,47 +1635,6 @@ class Interval:
1613
1635
  raise ValueError('Basis range [0, 4]. Unknown basis {basis}.')
1614
1636
 
1615
1637
 
1616
- Range = namedtuple('Range', ['start', 'end'])
1617
-
1618
-
1619
- def overlap_days(range_one, range_two, days=False):
1620
- """Test by how much two date ranges overlap
1621
- if `days=True`, we return an actual day count,
1622
- otherwise we just return if it overlaps True/False
1623
- poached from Raymond Hettinger http://stackoverflow.com/a/9044111
1624
-
1625
- >>> date1 = Date(2016, 3, 1)
1626
- >>> date2 = Date(2016, 3, 2)
1627
- >>> date3 = Date(2016, 3, 29)
1628
- >>> date4 = Date(2016, 3, 30)
1629
-
1630
- >>> assert overlap_days((date1, date3), (date2, date4))
1631
- >>> assert overlap_days((date2, date4), (date1, date3))
1632
- >>> assert not overlap_days((date1, date2), (date3, date4))
1633
-
1634
- >>> assert overlap_days((date1, date4), (date1, date4))
1635
- >>> assert overlap_days((date1, date4), (date2, date3))
1636
- >>> overlap_days((date1, date4), (date1, date4), True)
1637
- 30
1638
-
1639
- >>> assert overlap_days((date2, date3), (date1, date4))
1640
- >>> overlap_days((date2, date3), (date1, date4), True)
1641
- 28
1642
-
1643
- >>> assert not overlap_days((date3, date4), (date1, date2))
1644
- >>> overlap_days((date3, date4), (date1, date2), True)
1645
- -26
1646
- """
1647
- r1 = Range(*range_one)
1648
- r2 = Range(*range_two)
1649
- latest_start = max(r1.start, r2.start)
1650
- earliest_end = min(r1.end, r2.end)
1651
- overlap = (earliest_end - latest_start).days + 1
1652
- if days:
1653
- return overlap
1654
- return overlap >= 0
1655
-
1656
-
1657
1638
  def create_ics(begdate, enddate, summary, location):
1658
1639
  """Create a simple .ics file per RFC 5545 guidelines."""
1659
1640
 
date/extras.py ADDED
@@ -0,0 +1,90 @@
1
+ from collections import namedtuple
2
+
3
+ from date import NYSE, DateTime, Entity
4
+
5
+ __all__ = [
6
+ 'is_within_business_hours',
7
+ 'is_business_day',
8
+ 'overlap_days',
9
+ ]
10
+
11
+
12
+ def is_within_business_hours(entity: Entity = NYSE) -> bool:
13
+ """Return whether the current native datetime is between
14
+ open and close of business hours.
15
+
16
+ >>> from unittest.mock import patch
17
+ >>> tz = NYSE.tz
18
+
19
+ >>> with patch('date.DateTime.now') as mock:
20
+ ... mock.return_value = DateTime(2000, 5, 1, 12, 30, 0, 0, tzinfo=tz)
21
+ ... is_within_business_hours()
22
+ True
23
+
24
+ >>> with patch('date.DateTime.now') as mock:
25
+ ... mock.return_value = DateTime(2000, 7, 2, 12, 15, 0, 0, tzinfo=tz) # Sunday
26
+ ... is_within_business_hours()
27
+ False
28
+
29
+ >>> with patch('date.DateTime.now') as mock:
30
+ ... mock.return_value = DateTime(2000, 11, 1, 1, 15, 0, 0, tzinfo=tz)
31
+ ... is_within_business_hours()
32
+ False
33
+
34
+ """
35
+ this = DateTime.now()
36
+ this_entity = DateTime.now(tz=entity.tz).entity(entity)
37
+ bounds = this_entity.business_hours()
38
+ return this_entity.business_open() and (bounds[0] <= this.astimezone(entity.tz) <= bounds[1])
39
+
40
+
41
+ def is_business_day(entity: Entity = NYSE) -> bool:
42
+ """Return whether the current native datetime is a business day.
43
+ """
44
+ return DateTime.now(tz=entity.tz).entity(entity).is_business_day()
45
+
46
+
47
+ Range = namedtuple('Range', ['start', 'end'])
48
+
49
+
50
+ def overlap_days(range_one, range_two, days=False):
51
+ """Test by how much two date ranges overlap
52
+ if `days=True`, we return an actual day count,
53
+ otherwise we just return if it overlaps True/False
54
+ poached from Raymond Hettinger http://stackoverflow.com/a/9044111
55
+
56
+ >>> from date import Date
57
+ >>> date1 = Date(2016, 3, 1)
58
+ >>> date2 = Date(2016, 3, 2)
59
+ >>> date3 = Date(2016, 3, 29)
60
+ >>> date4 = Date(2016, 3, 30)
61
+
62
+ >>> assert overlap_days((date1, date3), (date2, date4))
63
+ >>> assert overlap_days((date2, date4), (date1, date3))
64
+ >>> assert not overlap_days((date1, date2), (date3, date4))
65
+
66
+ >>> assert overlap_days((date1, date4), (date1, date4))
67
+ >>> assert overlap_days((date1, date4), (date2, date3))
68
+ >>> overlap_days((date1, date4), (date1, date4), True)
69
+ 30
70
+
71
+ >>> assert overlap_days((date2, date3), (date1, date4))
72
+ >>> overlap_days((date2, date3), (date1, date4), True)
73
+ 28
74
+
75
+ >>> assert not overlap_days((date3, date4), (date1, date2))
76
+ >>> overlap_days((date3, date4), (date1, date2), True)
77
+ -26
78
+ """
79
+ r1 = Range(*range_one)
80
+ r2 = Range(*range_two)
81
+ latest_start = max(r1.start, r2.start)
82
+ earliest_end = min(r1.end, r2.end)
83
+ overlap = (earliest_end - latest_start).days + 1
84
+ if days:
85
+ return overlap
86
+ return overlap >= 0
87
+
88
+
89
+ if __name__ == '__main__':
90
+ __import__('doctest').testmod(optionflags=4 | 8 | 32)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: opendate
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary:
5
5
  Home-page: https://github.com/bissli/opendate
6
6
  License: MIT
@@ -49,7 +49,7 @@ thedate.business().add(days=5) # add 5 business day
49
49
 
50
50
  # subtract days
51
51
  thedate.subtract(days=5)
52
- thedate.business().subtrat(days=5) # subtract 5 business day
52
+ thedate.business().subtract(days=5) # subtract 5 business day
53
53
 
54
54
  # start of month
55
55
  thedate.start_of('month')
@@ -0,0 +1,7 @@
1
+ date/__init__.py,sha256=eB3ZluWh9M_QVfMOpmjeigLItgUl7mywdby88ffQfbE,2747
2
+ date/date.py,sha256=Z-8-5T8TfLtgiGe0ahK7QIgXjbBEDmrGRw8zEhiQD2Y,54819
3
+ date/extras.py,sha256=7xsOsdhKrmGoyLl5W4Xhg9TfuytaaIH7uKWW9PvR5sE,2832
4
+ opendate-0.1.4.dist-info/LICENSE,sha256=V4Rx8WWy7v8Fim6PHcEBszpZkDLbCHeorz1e_gr0Cbk,1111
5
+ opendate-0.1.4.dist-info/METADATA,sha256=up550EjO3j1IFI7F_iUrlugXe6rkcfpQpeRCQrEqgN8,1816
6
+ opendate-0.1.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
7
+ opendate-0.1.4.dist-info/RECORD,,
date/business.py DELETED
@@ -1,42 +0,0 @@
1
- from date import NYSE, DateTime, Entity
2
-
3
- __all__ = ['is_within_business_hours', 'is_business_day']
4
-
5
-
6
- def is_within_business_hours(entity: Entity = NYSE) -> bool:
7
- """Return whether the current native datetime is between
8
- open and close of business hours.
9
-
10
- >>> from unittest.mock import patch
11
- >>> tz = NYSE.tz
12
-
13
- >>> with patch('date.DateTime.now') as mock:
14
- ... mock.return_value = DateTime(2000, 5, 1, 12, 30, 0, 0, tzinfo=tz)
15
- ... is_within_business_hours()
16
- True
17
-
18
- >>> with patch('date.DateTime.now') as mock:
19
- ... mock.return_value = DateTime(2000, 7, 2, 12, 15, 0, 0, tzinfo=tz) # Sunday
20
- ... is_within_business_hours()
21
- False
22
-
23
- >>> with patch('date.DateTime.now') as mock:
24
- ... mock.return_value = DateTime(2000, 11, 1, 1, 15, 0, 0, tzinfo=tz)
25
- ... is_within_business_hours()
26
- False
27
-
28
- """
29
- this = DateTime.now()
30
- this_entity = DateTime.now(tz=entity.tz).entity(entity)
31
- bounds = this_entity.business_hours()
32
- return this_entity.business_open() and (bounds[0] <= this.astimezone(entity.tz) <= bounds[1])
33
-
34
-
35
- def is_business_day(entity: Entity = NYSE) -> bool:
36
- """Return whether the current native datetime is a business day.
37
- """
38
- return DateTime.now(tz=entity.tz).entity(entity).is_business_day()
39
-
40
-
41
- if __name__ == '__main__':
42
- __import__('doctest').testmod(optionflags=4 | 8 | 32)
@@ -1,7 +0,0 @@
1
- date/__init__.py,sha256=KRdrThrkKiQrf8b2VqAHx78hPCT1p0Tn0251k9ERFiE,2552
2
- date/business.py,sha256=g4dHpmEaUuADgMxIcTG96AEviaRo9NvGDJ8IPKXD7xQ,1386
3
- date/date.py,sha256=DrjvL_c3hYSHXaVVkccOpEyr7nDZvc02XUfSP8n_tNI,55210
4
- opendate-0.1.2.dist-info/LICENSE,sha256=V4Rx8WWy7v8Fim6PHcEBszpZkDLbCHeorz1e_gr0Cbk,1111
5
- opendate-0.1.2.dist-info/METADATA,sha256=qFurRfzxKJl1bx36as2o8KNXGufuQPYIhobsQOyFaDA,1815
6
- opendate-0.1.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
7
- opendate-0.1.2.dist-info/RECORD,,