opendate 0.1.9__tar.gz → 0.1.11__tar.gz

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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: opendate
3
- Version: 0.1.9
3
+ Version: 0.1.11
4
4
  Summary: Python business datetimes
5
5
  Home-page: https://github.com/bissli/opendate
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "opendate"
3
- version = "0.1.9"
3
+ version = "0.1.11"
4
4
  description = "Python business datetimes"
5
5
  authors = ["bissli <bissli.xyz@protonmail.com>"]
6
6
  readme = "README.md"
@@ -1,4 +1,4 @@
1
- __version__ = '0.1.9'
1
+ __version__ = '0.1.11'
2
2
 
3
3
  import datetime as _datetime
4
4
 
@@ -51,6 +51,10 @@ def time(*args, **kwargs):
51
51
  return Time(*args, **kwargs)
52
52
 
53
53
 
54
+ def interval(*args, **kwargs):
55
+ return Interval(*args, **kwargs)
56
+
57
+
54
58
  def parse(s: str | None, fmt: str = None, entity: Entity = NYSE, raise_err: bool = False) -> DateTime | None:
55
59
  """Parse using DateTime.parse
56
60
  """
@@ -60,14 +64,13 @@ def parse(s: str | None, fmt: str = None, entity: Entity = NYSE, raise_err: bool
60
64
  def instance(obj: _datetime.date | _datetime.datetime | _datetime.time) -> DateTime | Date | Time:
61
65
  """Create a DateTime/Date/Time instance from a datetime/date/time native one.
62
66
  """
63
- if isinstance(obj, DateTime | Date | Time):
64
- return obj
65
67
  if isinstance(obj, _datetime.date) and not isinstance(obj, _datetime.datetime):
66
68
  return Date.instance(obj)
67
69
  if isinstance(obj, _datetime.time):
68
70
  return Time.instance(obj)
69
71
  if isinstance(obj, _datetime.datetime):
70
72
  return DateTime.instance(obj)
73
+ raise ValueError(f'opendate `instance` helper cannot parse type {type(obj)}')
71
74
 
72
75
 
73
76
  def now(tz: str | _zoneinfo.ZoneInfo | None = None) -> DateTime:
@@ -84,28 +87,30 @@ def today(tz: str | _zoneinfo.ZoneInfo = None) -> DateTime:
84
87
 
85
88
  __all__ = [
86
89
  'Date',
90
+ 'date',
87
91
  'DateTime',
92
+ 'datetime',
93
+ 'Entity',
94
+ 'expect_date',
95
+ 'expect_datetime',
96
+ 'expect_native_timezone',
97
+ 'expect_utc_timezone',
98
+ 'instance',
88
99
  'Interval',
100
+ 'interval',
89
101
  'IntervalError',
90
- 'Time',
91
- 'WeekDay',
102
+ 'is_business_day',
103
+ 'is_within_business_hours',
104
+ 'LCL',
92
105
  'now',
93
- 'today',
106
+ 'NYSE',
107
+ 'overlap_days',
94
108
  'parse',
95
- 'LCL',
96
- 'timezone',
97
- 'expect_native_timezone',
98
- 'expect_utc_timezone',
99
109
  'prefer_native_timezone',
100
110
  'prefer_utc_timezone',
101
- 'expect_date',
102
- 'expect_datetime',
103
- 'Entity',
104
- 'NYSE',
105
- 'date',
106
- 'datetime',
111
+ 'Time',
107
112
  'time',
108
- 'overlap_days',
109
- 'is_within_business_hours',
110
- 'is_business_day',
113
+ 'timezone',
114
+ 'today',
115
+ 'WeekDay',
111
116
  ]
@@ -787,8 +787,18 @@ class Date(DateExtrasMixin, DateBusinessMixin, _pendulum.Date):
787
787
  raise TypeError(f'Invalid type for date parse: {s.__class__}')
788
788
 
789
789
  if fmt:
790
- with contextlib.suppress(ValueError):
790
+ try:
791
791
  return cls(*time.strptime(s, fmt)[:3])
792
+ except:
793
+ if raise_err:
794
+ raise ValueError(f'Unable to parse {s} using fmt {fmt}')
795
+ return
796
+
797
+ with contextlib.suppress(ValueError):
798
+ if float(s) and not len(s) == 8: # 20000101
799
+ if raise_err:
800
+ raise ValueError('Invalid date: %s', s)
801
+ return
792
802
 
793
803
  # special shortcode symbolic values: T, Y-2, P-1b
794
804
  if m := DATEMATCH.match(s):
@@ -810,7 +820,7 @@ class Date(DateExtrasMixin, DateBusinessMixin, _pendulum.Date):
810
820
  return cls.today().subtract(days=1)
811
821
 
812
822
  with contextlib.suppress(TypeError, ValueError):
813
- return cls.instance(_dateutil.parser.parse(s).date())
823
+ return cls.instance(_dateutil.parser.parse(s))
814
824
 
815
825
  # Regex with Month Numbers
816
826
  exps = (
@@ -1010,7 +1020,12 @@ class Time(_pendulum.Time):
1010
1020
  raise TypeError(f'Invalid type for time parse: {s.__class__}')
1011
1021
 
1012
1022
  if fmt:
1013
- return cls(*time.strptime(s, fmt)[3:6])
1023
+ try:
1024
+ return cls(*time.strptime(s, fmt)[3:6])
1025
+ except:
1026
+ if raise_err:
1027
+ raise ValueError(f'Unable to parse {s} using fmt {fmt}')
1028
+ return
1014
1029
 
1015
1030
  exps = (
1016
1031
  r'^(?P<h>\d{1,2})[:.](?P<m>\d{2})([:.](?P<s>\d{2})([.,](?P<u>\d+))?)?( +(?P<ap>[aApP][mM]))?$',
@@ -1028,7 +1043,7 @@ class Time(_pendulum.Time):
1028
1043
  return cls(hh, mm, ss, uu * 1000)
1029
1044
 
1030
1045
  with contextlib.suppress(TypeError, ValueError):
1031
- return cls.instance(_dateutil.parser.parse(s).time())
1046
+ return cls.instance(_dateutil.parser.parse(s))
1032
1047
 
1033
1048
  if raise_err:
1034
1049
  raise ValueError('Failed to parse time: %s', s)
@@ -1177,7 +1192,7 @@ class DateTime(DateBusinessMixin, _pendulum.DateTime):
1177
1192
  UTC time technically equals GMT
1178
1193
  >>> this_utc = DateTime.parse('Fri, 31 Oct 2014 18:55:00 GMT')
1179
1194
  >>> this_utc
1180
- DateTime(2014, 10, 31, 18, 55, 0, tzinfo=Timezone('UTC'))
1195
+ DateTime(2014, 10, 31, 18, 55, 0, tzinfo=tzutc())
1181
1196
 
1182
1197
  We can freely compare time zones
1183
1198
  >>> this_est1==this_est2==this_utc
@@ -1205,8 +1220,7 @@ class DateTime(DateBusinessMixin, _pendulum.DateTime):
1205
1220
  return cls.parse(iso).replace(tzinfo=LCL)
1206
1221
 
1207
1222
  with contextlib.suppress(ValueError, TypeError):
1208
- obj = _dateutil.parser.parse(s)
1209
- return cls.instance(_pendulum.instance(obj))
1223
+ return cls.instance(_dateutil.parser.parse(s))
1210
1224
 
1211
1225
  for delim in (' ', ':'):
1212
1226
  bits = s.split(delim, 1)
@@ -1356,12 +1370,29 @@ class Interval:
1356
1370
  set - set end=beg + num
1357
1371
  - set set beg=end - num
1358
1372
 
1359
- >>> Interval('4/3/2014', None).b.range(3)
1373
+ Basic/legacy cases
1374
+ >>> Interval(Date(2014, 4, 3), None).b.range(3)
1360
1375
  (Date(2014, 4, 3), Date(2014, 4, 8))
1361
1376
  >>> Interval(None, Date(2014, 7, 27)).range(20)
1362
1377
  (Date(2014, 7, 7), Date(2014, 7, 27))
1363
- >>> Interval(None, '2014/7/27').b.range(20)
1378
+ >>> Interval(None, Date(2014, 7, 27)).b.range(20)
1364
1379
  (Date(2014, 6, 27), Date(2014, 7, 27))
1380
+
1381
+ Do not modify dates if both are provided
1382
+ >>> Interval(Date(2024, 7, 25), Date(2024, 7, 25)).b.range(None)
1383
+ (Date(2024, 7, 25), Date(2024, 7, 25))
1384
+ >>> Interval(Date(2024, 7, 27), Date(2024, 7, 27)).b.range(None)
1385
+ (Date(2024, 7, 27), Date(2024, 7, 27))
1386
+
1387
+ Edge cases (7/27/24 is weekend)
1388
+ >>> Interval(Date(2024, 7, 27), None).b.range(0)
1389
+ (Date(2024, 7, 27), Date(2024, 7, 27))
1390
+ >>> Interval(None, Date(2024, 7, 27)).b.range(0)
1391
+ (Date(2024, 7, 27), Date(2024, 7, 27))
1392
+ >>> Interval(Date(2024, 7, 27), None).b.range(1)
1393
+ (Date(2024, 7, 27), Date(2024, 7, 29))
1394
+ >>> Interval(None, Date(2024, 7, 27)).b.range(1)
1395
+ (Date(2024, 7, 26), Date(2024, 7, 27))
1365
1396
  """
1366
1397
  begdate, enddate = self.begdate, self.enddate
1367
1398
 
@@ -1375,17 +1406,14 @@ class Interval:
1375
1406
  raise IntervalError('Missing begdate and enddate, window specified')
1376
1407
 
1377
1408
  if begdate and enddate:
1378
- return (begdate.business() if begdate._business else
1379
- begdate).add(days=window), \
1380
- (enddate.business() if enddate._business else
1381
- enddate).subtract(days=0)
1382
-
1383
- if (not begdate and not enddate) or enddate:
1384
- begdate = (enddate.business() if enddate._business else
1385
- enddate).subtract(days=window)
1409
+ pass # do nothing if both provided
1410
+ elif (not begdate and not enddate) or enddate:
1411
+ begdate = enddate.subtract(days=window) if window else enddate
1386
1412
  else:
1387
- enddate = (begdate.business() if begdate._business else
1388
- begdate).add(days=window)
1413
+ enddate = begdate.add(days=window) if window else begdate
1414
+
1415
+ enddate._business = False
1416
+ begdate._business = False
1389
1417
 
1390
1418
  return begdate, enddate
1391
1419
 
@@ -1491,13 +1519,13 @@ class Interval:
1491
1519
  def days(self) -> int:
1492
1520
  """Return days between (begdate, enddate] or negative (enddate, begdate].
1493
1521
 
1494
- >>> Interval(Date.parse('2018/9/6'), Date.parse('2018/9/10')).days()
1522
+ >>> Interval(Date(2018, 9, 6), Date(2018, 9, 10)).days()
1495
1523
  4
1496
- >>> Interval(Date.parse('2018/9/10'), Date.parse('2018/9/6')).days()
1524
+ >>> Interval(Date(2018, 9, 10), Date(2018, 9, 6)).days()
1497
1525
  -4
1498
- >>> Interval(Date.parse('2018/9/6'), Date.parse('2018/9/10')).b.days()
1526
+ >>> Interval(Date(2018, 9, 6), Date(2018, 9, 10)).b.days()
1499
1527
  2
1500
- >>> Interval(Date.parse('2018/9/10'), Date.parse('2018/9/6')).b.days()
1528
+ >>> Interval(Date(2018, 9, 10), Date(2018, 9, 6)).b.days()
1501
1529
  -2
1502
1530
  """
1503
1531
  assert self.begdate
File without changes
File without changes
File without changes