-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathdateutils.py
More file actions
125 lines (105 loc) · 3.3 KB
/
Copy pathdateutils.py
File metadata and controls
125 lines (105 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python
#
''' A few conveniences to do with dates and times.
There are some other PyPI modules providing richer date handling
than the stdlib `datetime` module.
This module mostly contains conveniences used in my other code;
you're welcome to it, but it does not pretend to be large or complete.
'''
from datetime import date, datetime, tzinfo, timedelta
from time import localtime, mktime, strftime
__version__ = '20250724-post'
DISTINFO = {
'keywords': ["date", "time", "datetime", "python", "python3"],
'classifiers': [
"Programming Language :: Python",
"Programming Language :: Python :: 3",
],
'install_requires': [],
}
class tzinfoHHMM(tzinfo):
''' tzinfo class based on +HHMM / -HHMM strings.
'''
def __init__(self, shhmm):
sign, hour, minute = shhmm[0], int(shhmm[1:3]), int(shhmm[3:5])
if sign == '+':
sign = 1
elif sign == '-':
sign = -1
else:
raise ValueError(
"%s: invalid sign '%s', should be '+' or '-'" % (
shhmm,
sign,
)
)
self._tzname = shhmm
self.sign = sign
self.hour = hour
self.minute = minute
def utcoffset(self, dt):
return self.hour * 60 + self.minute
def dst(self, dt):
return timedelta(0)
def tzname(self, dt):
return self._tzname
try:
from datetime import timezone # pylint: disable=ungrouped-imports
except ImportError:
UTC = tzinfoHHMM('+0000')
else:
UTC = timezone.utc
def isodate(when=None, dashed=True):
''' Return a date in ISO8601 YYYY-MM-DD format, or YYYYMMDD if not `dashed`.
Modern Pythons have a `datetime.isoformat` method, you should use that.
'''
if when is None:
when = localtime()
if dashed:
format_s = '%Y-%m-%d'
else:
format_s = '%Y%m%d'
return strftime(format_s, when)
def datetime2unixtime(dt):
''' Convert a timezone aware `datetime` to a UNIX timestamp.
*WARNING*: a naive datetime is assumed to be in UTC.
'''
if dt.tzinfo is None:
dt = dt.replace(tzinfo=UTC)
return dt.timestamp()
def unixtime2datetime(unixtime, *, tz: tzinfo = UTC):
''' Convert a a UNIX timestamp to a `datetime` in the timezone `tz`.
*Note*: the default timezone is UTC, not the local timezone.
'''
return datetime.fromtimestamp(unixtime, tz=tz)
def localdate2unixtime(d):
''' Convert a localtime `date` into a UNIX timestamp.
'''
return mktime(date(d.year, d.month, d.day).timetuple())
class UNIXTimeMixin:
''' A mixin for classes with a `.unixtime` attribute,
a `float` storing a UNIX timestamp.
'''
def as_datetime(self, tz: tzinfo = UTC):
''' Return `self.unixtime` as a `datetime`
with the timezone `tz` (default `UTC`).
'''
if not isinstance(tz, tzinfo):
raise TypeError(
'not a datetime.tzinfo instance: tz=%s:%r' %
(tz.__class__.__name__, tz)
)
return unixtime2datetime(self.unixtime, tz=tz)
@property
def datetime(self):
''' The `unixtime` as a UTC `datetime`.
'''
return self.as_datetime(UTC)
@datetime.setter
def datetime(self, dt):
''' Set the `unixtime` from a `datetime`.
The `datetime` may not be naive (`tz.tzinfo` may not be `None`).
'''
if dt.tzinfo is None:
raise ValueError('naive datetime %r' % (dt,))
self.unixtime = dt.timestamp()