@@ -87,173 +87,185 @@ def get_timezone(tz: str, date: Optional[datetime.datetime] = None) -> Optional[
87
87
88
88
return pytz .timezone (tz ).localize (d ).tzinfo
89
89
90
- def current_tzinfo () -> Optional [datetime .tzinfo ]:
91
- """
92
- Returns a tzinfo object for the current timezone
90
+ except ImportError as e :
93
91
94
- :rtype: :class:`python:datetime.tzinfo`
95
- """
92
+ # stdlib
93
+ import warnings
96
94
97
- return datetime .datetime .now ().astimezone ().tzinfo # pragma: no cover (hard to test)
98
-
99
- #
100
- # def datetime_to_utc_timestamp(datetime, current_tzinfo=None):
101
- # """
102
- # Convert a :class:`datetime.datetime` object to seconds since UNIX epoch, in UTC time
103
- #
104
- # :param datetime:
105
- # :type datetime: :class:`datetime.datetime`
106
- # :param current_tzinfo: A tzinfo object representing the current timezone.
107
- # If None it will be inferred.
108
- # :type current_tzinfo: :class:`~python:datetime.tzinfo`
109
- #
110
- # :return: Timestamp in UTC timezone
111
- # :rtype: float
112
- # """
113
- #
114
- # return datetime.astimezone(current_tzinfo).timestamp()
115
- #
116
-
117
- def set_timezone (obj : datetime .datetime , tzinfo : datetime .tzinfo ) -> datetime .datetime :
118
- """
119
- Sets the timezone / tzinfo of the given :class:`datetime.datetime` object.
120
- This will not convert the time (i.e. the hours will stay the same).
121
- Use :meth:`python:datetime.datetime.astimezone` to accomplish that.
95
+ warnings .warn (
96
+ f"""\
97
+ Some functions in 'domdf_python_tools.dates' require pytz (https://pypi.org/project/pytz/), but it could not be imported.
98
+ The error was { e } .
99
+ """ ,
100
+ )
122
101
123
- :param obj:
124
- :param tzinfo:
125
102
126
- :return:
127
- """
103
+ def current_tzinfo () -> Optional [datetime .tzinfo ]:
104
+ """
105
+ Returns a tzinfo object for the current timezone
128
106
129
- return obj .replace (tzinfo = tzinfo )
107
+ :rtype: :class:`python:datetime.tzinfo`
108
+ """
130
109
131
- def utc_timestamp_to_datetime (
132
- utc_timestamp : Union [float , int ],
133
- output_tz : Optional [datetime .tzinfo ] = None ,
134
- ) -> datetime .datetime :
135
- """
136
- Convert UTC timestamp (seconds from UNIX epoch) to a :class:`datetime.datetime` object.
110
+ return datetime .datetime .now ().astimezone ().tzinfo # pragma: no cover (hard to test)
137
111
138
- If ``output_tz`` is None the timestamp is converted to the platform’s local date and time,
139
- and the local timezone is inferred and set for the object.
140
112
141
- If ``output_tz`` is not None, it must be an instance of a :class:`~python:datetime.tzinfo` subclass,
142
- and the timestamp is converted to ``output_tz``’s time zone.
113
+ #
114
+ # def datetime_to_utc_timestamp(datetime, current_tzinfo=None):
115
+ # """
116
+ # Convert a :class:`datetime.datetime` object to seconds since UNIX epoch, in UTC time
117
+ #
118
+ # :param datetime:
119
+ # :type datetime: :class:`datetime.datetime`
120
+ # :param current_tzinfo: A tzinfo object representing the current timezone.
121
+ # If None it will be inferred.
122
+ # :type current_tzinfo: :class:`~python:datetime.tzinfo`
123
+ #
124
+ # :return: Timestamp in UTC timezone
125
+ # :rtype: float
126
+ # """
127
+ #
128
+ # return datetime.astimezone(current_tzinfo).timestamp()
129
+ #
143
130
144
131
145
- :param utc_timestamp: The timestamp to convert to a datetime object
146
- :type utc_timestamp: float, int
147
- :param output_tz: The timezone to output the datetime object for .
148
- If None it will be inferred .
149
- :type output_tz: datetime.tzinfo, optional
132
+ def set_timezone ( obj : datetime . datetime , tzinfo : datetime . tzinfo ) -> datetime . datetime :
133
+ """
134
+ Sets the timezone / tzinfo of the given :class:` datetime.datetime` object.
135
+ This will not convert the time (i.e. the hours will stay the same) .
136
+ Use :meth:`python: datetime.datetime.astimezone` to accomplish that.
150
137
151
- :return: The timestamp as a datetime object.
152
- :rtype: datetime.datetime
138
+ :param obj:
139
+ :param tzinfo:
153
140
154
- :raises: :class:`~python:OverflowError` if the timestamp is out of the range
155
- of values supported by the platform C localtime() or gmtime() functions,
156
- and OSError on localtime() or gmtime() failure. It’s common for this to
157
- be restricted to years in 1970 through 2038.
158
- """
141
+ :return:
142
+ """
159
143
160
- new_datetime = datetime .datetime .fromtimestamp (utc_timestamp , output_tz )
161
- return new_datetime .astimezone (output_tz )
162
-
163
- # List of months and their 3-character shortcodes.
164
- months = OrderedDict (
165
- Jan = "January" ,
166
- Feb = "February" ,
167
- Mar = "March" ,
168
- Apr = "April" ,
169
- May = "May" ,
170
- Jun = "June" ,
171
- Jul = "July" ,
172
- Aug = "August" ,
173
- Sep = "September" ,
174
- Oct = "October" ,
175
- Nov = "November" ,
176
- Dec = "December" ,
177
- )
144
+ return obj .replace (tzinfo = tzinfo )
178
145
179
- def parse_month (month : Union [str , int ]) -> str :
180
- """
181
- Converts an integer or shorthand month into the full month name.
182
146
183
- :param month: The month number or shorthand name
184
- :type month: str or int
147
+ def utc_timestamp_to_datetime (
148
+ utc_timestamp : Union [float , int ],
149
+ output_tz : Optional [datetime .tzinfo ] = None ,
150
+ ) -> datetime .datetime :
151
+ """
152
+ Convert UTC timestamp (seconds from UNIX epoch) to a :class:`datetime.datetime` object.
185
153
186
- :return: The full name of the month
187
- :rtype: str
188
- """
154
+ If ``output_tz`` is None the timestamp is converted to the platform’s local date and time,
155
+ and the local timezone is inferred and set for the object.
189
156
190
- try :
191
- month = int (month )
192
- except ValueError :
193
- try :
194
- return months [month .capitalize ()[:3 ]] # type: ignore
195
- except KeyError :
196
- raise ValueError ("Unrecognised month value" )
197
-
198
- # Only get here if first try succeeded
199
- if 0 < month <= 12 :
200
- return list (months .values ())[month - 1 ]
201
- else :
202
- raise ValueError ("Unrecognised month value" )
157
+ If ``output_tz`` is not None, it must be an instance of a :class:`~python:datetime.tzinfo` subclass,
158
+ and the timestamp is converted to ``output_tz``’s time zone.
203
159
204
- def get_month_number (month : Union [str , int ]) -> int :
205
- """
206
- Returns the number of the given month.
207
- If ``month`` is already a number between 1 and 12 it will be returned immediately.
208
160
209
- :param month: The month to convert to a number
210
- :type month: str or int
161
+ :param utc_timestamp: The timestamp to convert to a datetime object
162
+ :type utc_timestamp: float, int
163
+ :param output_tz: The timezone to output the datetime object for.
164
+ If None it will be inferred.
165
+ :type output_tz: datetime.tzinfo, optional
211
166
212
- :return: The number of the month
213
- :rtype: int
214
- """
167
+ :return: The timestamp as a datetime object.
168
+ :rtype: datetime.datetime
215
169
216
- if isinstance (month , int ):
217
- if 0 < month <= 12 :
218
- return month
219
- else :
220
- raise ValueError ("The given month is not recognised." )
221
- else :
222
- month = parse_month (month )
223
- return list (months .values ()).index (month ) + 1
170
+ :raises: :class:`~python:OverflowError` if the timestamp is out of the range
171
+ of values supported by the platform C localtime() or gmtime() functions,
172
+ and OSError on localtime() or gmtime() failure. It’s common for this to
173
+ be restricted to years in 1970 through 2038.
174
+ """
224
175
225
- def check_date (month : Union [str , int ], day : int , leap_year : bool = True ) -> bool :
226
- """
227
- Returns :py:obj:`True` if the day number is valid for the given month.
228
- Note that this will return :py:obj:`True` for the 29th Feb. If you don't
229
- want this behaviour set ``leap_year`` to :py:obj:`False`.
230
-
231
- :param month: The month to test.
232
- :type month: str, int
233
- :param day: The day number to test.
234
- :type day: int
235
- :param leap_year: Whether to return :py:obj:`True` for 29th Feb. Default :py:obj:`True`.
236
- :type leap_year: bool, optional
237
-
238
- :return: :py:obj:`True` if the date is valid.
239
- :rtype: bool
240
- """
176
+ new_datetime = datetime .datetime .fromtimestamp (utc_timestamp , output_tz )
177
+ return new_datetime .astimezone (output_tz )
178
+
179
+
180
+ # List of months and their 3-character shortcodes.
181
+ months = OrderedDict (
182
+ Jan = "January" ,
183
+ Feb = "February" ,
184
+ Mar = "March" ,
185
+ Apr = "April" ,
186
+ May = "May" ,
187
+ Jun = "June" ,
188
+ Jul = "July" ,
189
+ Aug = "August" ,
190
+ Sep = "September" ,
191
+ Oct = "October" ,
192
+ Nov = "November" ,
193
+ Dec = "December" ,
194
+ )
195
+
196
+
197
+ def parse_month (month : Union [str , int ]) -> str :
198
+ """
199
+ Converts an integer or shorthand month into the full month name.
200
+
201
+ :param month: The month number or shorthand name
202
+ :type month: str or int
241
203
242
- # Ensure day is an integer
243
- day = int (day )
244
- month = get_month_number (month )
245
- year = 2020 if leap_year else 2019
204
+ :return: The full name of the month
205
+ :rtype: str
206
+ """
246
207
208
+ try :
209
+ month = int (month )
210
+ except ValueError :
247
211
try :
248
- datetime .date (year , month , day )
249
- return True
250
- except ValueError :
251
- return False
212
+ return months [month .capitalize ()[:3 ]] # type: ignore
213
+ except KeyError :
214
+ raise ValueError ("Unrecognised month value" )
252
215
253
- except ImportError :
216
+ # Only get here if first try succeeded
217
+ if 0 < month <= 12 :
218
+ return list (months .values ())[month - 1 ]
219
+ else :
220
+ raise ValueError ("Unrecognised month value" )
254
221
255
- # stdlib
256
- import warnings
257
- warnings .warn (
258
- "'domdf_python_tools.dates' requires pytz (https://pypi.org/project/pytz/), but it is not installed." ,
259
- )
222
+
223
+ def get_month_number (month : Union [str , int ]) -> int :
224
+ """
225
+ Returns the number of the given month.
226
+ If ``month`` is already a number between 1 and 12 it will be returned immediately.
227
+
228
+ :param month: The month to convert to a number
229
+ :type month: str or int
230
+
231
+ :return: The number of the month
232
+ :rtype: int
233
+ """
234
+
235
+ if isinstance (month , int ):
236
+ if 0 < month <= 12 :
237
+ return month
238
+ else :
239
+ raise ValueError ("The given month is not recognised." )
240
+ else :
241
+ month = parse_month (month )
242
+ return list (months .values ()).index (month ) + 1
243
+
244
+
245
+ def check_date (month : Union [str , int ], day : int , leap_year : bool = True ) -> bool :
246
+ """
247
+ Returns :py:obj:`True` if the day number is valid for the given month.
248
+ Note that this will return :py:obj:`True` for the 29th Feb. If you don't
249
+ want this behaviour set ``leap_year`` to :py:obj:`False`.
250
+
251
+ :param month: The month to test.
252
+ :type month: str, int
253
+ :param day: The day number to test.
254
+ :type day: int
255
+ :param leap_year: Whether to return :py:obj:`True` for 29th Feb. Default :py:obj:`True`.
256
+ :type leap_year: bool, optional
257
+
258
+ :return: :py:obj:`True` if the date is valid.
259
+ :rtype: bool
260
+ """
261
+
262
+ # Ensure day is an integer
263
+ day = int (day )
264
+ month = get_month_number (month )
265
+ year = 2020 if leap_year else 2019
266
+
267
+ try :
268
+ datetime .date (year , month , day )
269
+ return True
270
+ except ValueError :
271
+ return False
0 commit comments