dfdatetime 20260730__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.
@@ -0,0 +1,501 @@
1
+ """POSIX timestamp implementation."""
2
+
3
+ import decimal
4
+
5
+ from dfdatetime import definitions
6
+ from dfdatetime import factory
7
+ from dfdatetime import interface
8
+
9
+
10
+ class PosixTimeEpoch(interface.DateTimeEpoch):
11
+ """POSIX time epoch."""
12
+
13
+ def __init__(self):
14
+ """Initializes a POSIX time epoch."""
15
+ super().__init__(1970, 1, 1)
16
+
17
+
18
+ class PosixTime(interface.DateTimeValues):
19
+ """POSIX timestamp.
20
+
21
+ The POSIX timestamp is a signed integer that contains the number of
22
+ seconds since 1970-01-01 00:00:00 (also known as the POSIX epoch).
23
+ Negative values represent date and times predating the POSIX epoch.
24
+
25
+ The POSIX timestamp was initially 32-bit though 64-bit variants
26
+ are known to be used.
27
+
28
+ Attributes:
29
+ is_local_time (bool): True if the date and time value is in local time.
30
+ """
31
+
32
+ _EPOCH = PosixTimeEpoch()
33
+
34
+ def __init__(self, precision=None, time_zone_offset=None, timestamp=None):
35
+ """Initializes a POSIX timestamp.
36
+
37
+ Args:
38
+ precision (Optional[str]): precision of the date and time value, which
39
+ should be one of the PRECISION_VALUES in definitions.
40
+ time_zone_offset (Optional[int]): time zone offset in number of minutes
41
+ from UTC or None if not set.
42
+ timestamp (Optional[int]): POSIX timestamp.
43
+ """
44
+ super().__init__(
45
+ precision=precision or definitions.PRECISION_1_SECOND,
46
+ time_zone_offset=time_zone_offset,
47
+ )
48
+ self._timestamp = timestamp
49
+
50
+ @property
51
+ def timestamp(self):
52
+ """int: POSIX timestamp or None if not set."""
53
+ return self._timestamp
54
+
55
+ def _GetNormalizedTimestamp(self):
56
+ """Retrieves the normalized timestamp.
57
+
58
+ Returns:
59
+ decimal.Decimal: normalized timestamp, which contains the number of
60
+ seconds since January 1, 1970 00:00:00 and a fraction of second used
61
+ for increased precision, or None if the normalized timestamp cannot be
62
+ determined.
63
+ """
64
+ if self._normalized_timestamp is None:
65
+ if self._timestamp is not None:
66
+ self._normalized_timestamp = decimal.Decimal(self._timestamp)
67
+
68
+ if self._time_zone_offset:
69
+ self._normalized_timestamp -= self._time_zone_offset * 60
70
+
71
+ return self._normalized_timestamp
72
+
73
+ def CopyFromDateTimeString(self, time_string):
74
+ """Copies a POSIX timestamp from a date and time string.
75
+
76
+ Args:
77
+ time_string (str): date and time value formatted as:
78
+ YYYY-MM-DD hh:mm:ss.######[+-]##:##
79
+
80
+ Where # are numeric digits ranging from 0 to 9 and the seconds
81
+ fraction can be either 3, 6 or 9 digits. The time of day, seconds
82
+ fraction and time zone offset are optional. The default time zone
83
+ is UTC.
84
+ """
85
+ date_time_values = self._CopyDateTimeFromString(time_string)
86
+
87
+ year = date_time_values.get("year", 0)
88
+ month = date_time_values.get("month", 0)
89
+ day_of_month = date_time_values.get("day_of_month", 0)
90
+ hours = date_time_values.get("hours", 0)
91
+ minutes = date_time_values.get("minutes", 0)
92
+ seconds = date_time_values.get("seconds", 0)
93
+ time_zone_offset = date_time_values.get("time_zone_offset")
94
+
95
+ self._timestamp = self._GetNumberOfSecondsFromElements(
96
+ year, month, day_of_month, hours, minutes, seconds
97
+ )
98
+ self._time_zone_offset = time_zone_offset
99
+
100
+ def CopyToDateTimeString(self):
101
+ """Copies the POSIX timestamp to a date and time string.
102
+
103
+ Returns:
104
+ str: date and time value formatted as: "YYYY-MM-DD hh:mm:ss" or None
105
+ if the timestamp is missing.
106
+ """
107
+ if self._timestamp is None:
108
+ return None
109
+
110
+ number_of_days, hours, minutes, seconds = self._GetTimeValues(self._timestamp)
111
+
112
+ year, month, day_of_month = self._GetDateValuesWithEpoch(
113
+ number_of_days, self._EPOCH
114
+ )
115
+ return (
116
+ f"{year:04d}-{month:02d}-{day_of_month:02d} "
117
+ f"{hours:02d}:{minutes:02d}:{seconds:02d}"
118
+ )
119
+
120
+ def CopyToSerializableDict(self):
121
+ """Copies the date time value to a serializable dictionary.
122
+
123
+ Returns:
124
+ dict[str, object]: serializable dictionary.
125
+ """
126
+ serializable_dict = self._CreateSerializableDict()
127
+
128
+ serializable_dict["timestamp"] = self._timestamp
129
+
130
+ return serializable_dict
131
+
132
+
133
+ class PosixTimeInMilliseconds(interface.DateTimeValues):
134
+ """POSIX timestamp in milliseconds.
135
+
136
+ Variant of the POSIX timestamp in milliseconds.
137
+
138
+ Attributes:
139
+ is_local_time (bool): True if the date and time value is in local time.
140
+ """
141
+
142
+ _EPOCH = PosixTimeEpoch()
143
+
144
+ def __init__(self, precision=None, time_zone_offset=None, timestamp=None):
145
+ """Initializes a POSIX timestamp in milliseconds.
146
+
147
+ Args:
148
+ precision (Optional[str]): precision of the date and time value, which
149
+ should be one of the PRECISION_VALUES in definitions.
150
+ time_zone_offset (Optional[int]): time zone offset in number of minutes
151
+ from UTC or None if not set.
152
+ timestamp (Optional[int]): POSIX timestamp in milliseconds.
153
+ """
154
+ super().__init__(
155
+ precision=precision or definitions.PRECISION_1_MILLISECOND,
156
+ time_zone_offset=time_zone_offset,
157
+ )
158
+ self._timestamp = timestamp
159
+
160
+ @property
161
+ def timestamp(self):
162
+ """int: POSIX timestamp in milliseconds or None if not set."""
163
+ return self._timestamp
164
+
165
+ def _GetNormalizedTimestamp(self):
166
+ """Retrieves the normalized timestamp.
167
+
168
+ Returns:
169
+ decimal.Decimal: normalized timestamp, which contains the number of
170
+ seconds since January 1, 1970 00:00:00 and a fraction of second used
171
+ for increased precision, or None if the normalized timestamp cannot be
172
+ determined.
173
+ """
174
+ if self._normalized_timestamp is None:
175
+ if self._timestamp is not None:
176
+ self._normalized_timestamp = (
177
+ decimal.Decimal(self._timestamp)
178
+ / definitions.MILLISECONDS_PER_SECOND
179
+ )
180
+ if self._time_zone_offset:
181
+ self._normalized_timestamp -= self._time_zone_offset * 60
182
+
183
+ return self._normalized_timestamp
184
+
185
+ def CopyFromDateTimeString(self, time_string):
186
+ """Copies a POSIX timestamp from a date and time string.
187
+
188
+ Args:
189
+ time_string (str): date and time value formatted as:
190
+ YYYY-MM-DD hh:mm:ss.######[+-]##:##
191
+
192
+ Where # are numeric digits ranging from 0 to 9 and the seconds
193
+ fraction can be either 3, 6 or 9 digits. The time of day, seconds
194
+ fraction and time zone offset are optional. The default time zone
195
+ is UTC.
196
+ """
197
+ date_time_values = self._CopyDateTimeFromString(time_string)
198
+
199
+ year = date_time_values.get("year", 0)
200
+ month = date_time_values.get("month", 0)
201
+ day_of_month = date_time_values.get("day_of_month", 0)
202
+ hours = date_time_values.get("hours", 0)
203
+ minutes = date_time_values.get("minutes", 0)
204
+ seconds = date_time_values.get("seconds", 0)
205
+ nanoseconds = date_time_values.get("nanoseconds", 0)
206
+ time_zone_offset = date_time_values.get("time_zone_offset")
207
+
208
+ milliseconds, _ = divmod(nanoseconds, definitions.NANOSECONDS_PER_MILLISECOND)
209
+
210
+ timestamp = self._GetNumberOfSecondsFromElements(
211
+ year, month, day_of_month, hours, minutes, seconds
212
+ )
213
+ timestamp *= definitions.MILLISECONDS_PER_SECOND
214
+ timestamp += milliseconds
215
+
216
+ self._timestamp = timestamp
217
+ self._time_zone_offset = time_zone_offset
218
+
219
+ def CopyToDateTimeString(self):
220
+ """Copies the POSIX timestamp to a date and time string.
221
+
222
+ Returns:
223
+ str: date and time value formatted as: "YYYY-MM-DD hh:mm:ss.######" or
224
+ None if the timestamp is missing.
225
+ """
226
+ if self._timestamp is None:
227
+ return None
228
+
229
+ timestamp, milliseconds = divmod(
230
+ self._timestamp, definitions.MILLISECONDS_PER_SECOND
231
+ )
232
+ number_of_days, hours, minutes, seconds = self._GetTimeValues(timestamp)
233
+
234
+ year, month, day_of_month = self._GetDateValuesWithEpoch(
235
+ number_of_days, self._EPOCH
236
+ )
237
+ return (
238
+ f"{year:04d}-{month:02d}-{day_of_month:02d} "
239
+ f"{hours:02d}:{minutes:02d}:{seconds:02d}.{milliseconds:03d}"
240
+ )
241
+
242
+ def CopyToSerializableDict(self):
243
+ """Copies the date time value to a serializable dictionary.
244
+
245
+ Returns:
246
+ dict[str, object]: serializable dictionary.
247
+ """
248
+ serializable_dict = self._CreateSerializableDict()
249
+
250
+ serializable_dict["timestamp"] = self._timestamp
251
+
252
+ return serializable_dict
253
+
254
+
255
+ class PosixTimeInMicroseconds(interface.DateTimeValues):
256
+ """POSIX timestamp in microseconds.
257
+
258
+ Variant of the POSIX timestamp in microseconds.
259
+
260
+ Attributes:
261
+ is_local_time (bool): True if the date and time value is in local time.
262
+ """
263
+
264
+ _EPOCH = PosixTimeEpoch()
265
+
266
+ def __init__(self, precision=None, time_zone_offset=None, timestamp=None):
267
+ """Initializes a POSIX timestamp in microseconds.
268
+
269
+ Args:
270
+ precision (Optional[str]): precision of the date and time value, which
271
+ should be one of the PRECISION_VALUES in definitions.
272
+ time_zone_offset (Optional[int]): time zone offset in number of minutes
273
+ from UTC or None if not set.
274
+ timestamp (Optional[int]): POSIX timestamp in microseconds.
275
+ """
276
+ super().__init__(
277
+ precision=precision or definitions.PRECISION_1_MICROSECOND,
278
+ time_zone_offset=time_zone_offset,
279
+ )
280
+ self._timestamp = timestamp
281
+
282
+ @property
283
+ def timestamp(self):
284
+ """int: POSIX timestamp in microseconds or None if not set."""
285
+ return self._timestamp
286
+
287
+ def _GetNormalizedTimestamp(self):
288
+ """Retrieves the normalized timestamp.
289
+
290
+ Returns:
291
+ decimal.Decimal: normalized timestamp, which contains the number of
292
+ seconds since January 1, 1970 00:00:00 and a fraction of second used
293
+ for increased precision, or None if the normalized timestamp cannot be
294
+ determined.
295
+ """
296
+ if self._normalized_timestamp is None:
297
+ if self._timestamp is not None:
298
+ self._normalized_timestamp = (
299
+ decimal.Decimal(self._timestamp)
300
+ / definitions.MICROSECONDS_PER_SECOND
301
+ )
302
+ if self._time_zone_offset:
303
+ self._normalized_timestamp -= self._time_zone_offset * 60
304
+
305
+ return self._normalized_timestamp
306
+
307
+ def CopyFromDateTimeString(self, time_string):
308
+ """Copies a POSIX timestamp from a date and time string.
309
+
310
+ Args:
311
+ time_string (str): date and time value formatted as:
312
+ YYYY-MM-DD hh:mm:ss.######[+-]##:##
313
+
314
+ Where # are numeric digits ranging from 0 to 9 and the seconds
315
+ fraction can be either 3, 6 or 9 digits. The time of day, seconds
316
+ fraction and time zone offset are optional. The default time zone
317
+ is UTC.
318
+ """
319
+ date_time_values = self._CopyDateTimeFromString(time_string)
320
+
321
+ year = date_time_values.get("year", 0)
322
+ month = date_time_values.get("month", 0)
323
+ day_of_month = date_time_values.get("day_of_month", 0)
324
+ hours = date_time_values.get("hours", 0)
325
+ minutes = date_time_values.get("minutes", 0)
326
+ seconds = date_time_values.get("seconds", 0)
327
+ nanoseconds = date_time_values.get("nanoseconds", 0)
328
+ time_zone_offset = date_time_values.get("time_zone_offset")
329
+
330
+ milliseconds, _ = divmod(nanoseconds, definitions.NANOSECONDS_PER_MICROSECOND)
331
+
332
+ timestamp = self._GetNumberOfSecondsFromElements(
333
+ year, month, day_of_month, hours, minutes, seconds
334
+ )
335
+ timestamp *= definitions.MICROSECONDS_PER_SECOND
336
+ timestamp += milliseconds
337
+
338
+ self._timestamp = timestamp
339
+ self._time_zone_offset = time_zone_offset
340
+
341
+ def CopyToDateTimeString(self):
342
+ """Copies the POSIX timestamp to a date and time string.
343
+
344
+ Returns:
345
+ str: date and time value formatted as: "YYYY-MM-DD hh:mm:ss.######" or
346
+ None if the timestamp is missing.
347
+ """
348
+ if self._timestamp is None:
349
+ return None
350
+
351
+ timestamp, microseconds = divmod(
352
+ self._timestamp, definitions.MICROSECONDS_PER_SECOND
353
+ )
354
+ number_of_days, hours, minutes, seconds = self._GetTimeValues(timestamp)
355
+
356
+ year, month, day_of_month = self._GetDateValuesWithEpoch(
357
+ number_of_days, self._EPOCH
358
+ )
359
+ return (
360
+ f"{year:04d}-{month:02d}-{day_of_month:02d} "
361
+ f"{hours:02d}:{minutes:02d}:{seconds:02d}.{microseconds:06d}"
362
+ )
363
+
364
+ def CopyToSerializableDict(self):
365
+ """Copies the date time value to a serializable dictionary.
366
+
367
+ Returns:
368
+ dict[str, object]: serializable dictionary.
369
+ """
370
+ serializable_dict = self._CreateSerializableDict()
371
+
372
+ serializable_dict["timestamp"] = self._timestamp
373
+
374
+ return serializable_dict
375
+
376
+
377
+ class PosixTimeInNanoseconds(interface.DateTimeValues):
378
+ """POSIX timestamp in nanoseconds.
379
+
380
+ Variant of the POSIX timestamp in nanoseconds.
381
+
382
+ Attributes:
383
+ is_local_time (bool): True if the date and time value is in local time.
384
+ """
385
+
386
+ _EPOCH = PosixTimeEpoch()
387
+
388
+ def __init__(self, precision=None, time_zone_offset=None, timestamp=None):
389
+ """Initializes a POSIX timestamp in nanoseconds.
390
+
391
+ Args:
392
+ precision (Optional[str]): precision of the date and time value, which
393
+ should be one of the PRECISION_VALUES in definitions.
394
+ time_zone_offset (Optional[int]): time zone offset in number of minutes
395
+ from UTC or None if not set.
396
+ timestamp (Optional[int]): POSIX timestamp in nanoseconds.
397
+ """
398
+ super().__init__(
399
+ precision=precision or definitions.PRECISION_1_NANOSECOND,
400
+ time_zone_offset=time_zone_offset,
401
+ )
402
+ self._timestamp = timestamp
403
+
404
+ @property
405
+ def timestamp(self):
406
+ """int: POSIX timestamp or None if not set."""
407
+ return self._timestamp
408
+
409
+ def _GetNormalizedTimestamp(self):
410
+ """Retrieves the normalized timestamp.
411
+
412
+ Returns:
413
+ decimal.Decimal: normalized timestamp, which contains the number of
414
+ seconds since January 1, 1970 00:00:00 and a fraction of second used
415
+ for increased precision, or None if the normalized timestamp cannot be
416
+ determined.
417
+ """
418
+ if self._normalized_timestamp is None:
419
+ if self._timestamp is not None:
420
+ self._normalized_timestamp = (
421
+ decimal.Decimal(self._timestamp)
422
+ / definitions.NANOSECONDS_PER_SECOND
423
+ )
424
+ if self._time_zone_offset:
425
+ self._normalized_timestamp -= self._time_zone_offset * 60
426
+
427
+ return self._normalized_timestamp
428
+
429
+ def CopyFromDateTimeString(self, time_string):
430
+ """Copies a POSIX timestamp from a date and time string.
431
+
432
+ Args:
433
+ time_string (str): date and time value formatted as:
434
+ YYYY-MM-DD hh:mm:ss.######[+-]##:##
435
+
436
+ Where # are numeric digits ranging from 0 to 9 and the seconds
437
+ fraction can be either 3, 6 or 9 digits. The time of day, seconds
438
+ fraction and time zone offset are optional. The default time zone
439
+ is UTC.
440
+ """
441
+ date_time_values = self._CopyDateTimeFromString(time_string)
442
+
443
+ year = date_time_values.get("year", 0)
444
+ month = date_time_values.get("month", 0)
445
+ day_of_month = date_time_values.get("day_of_month", 0)
446
+ hours = date_time_values.get("hours", 0)
447
+ minutes = date_time_values.get("minutes", 0)
448
+ seconds = date_time_values.get("seconds", 0)
449
+ nanoseconds = date_time_values.get("nanoseconds", 0)
450
+ time_zone_offset = date_time_values.get("time_zone_offset")
451
+
452
+ timestamp = self._GetNumberOfSecondsFromElements(
453
+ year, month, day_of_month, hours, minutes, seconds
454
+ )
455
+ timestamp *= definitions.NANOSECONDS_PER_SECOND
456
+ timestamp += nanoseconds
457
+
458
+ self._normalized_timestamp = None
459
+ self._timestamp = timestamp
460
+ self._time_zone_offset = time_zone_offset
461
+
462
+ def CopyToDateTimeString(self):
463
+ """Copies the POSIX timestamp to a date and time string.
464
+
465
+ Returns:
466
+ str: date and time value formatted as: "YYYY-MM-DD hh:mm:ss.#########" or
467
+ None if the timestamp is missing or invalid.
468
+ """
469
+ if self._timestamp is None:
470
+ return None
471
+
472
+ timestamp, nanoseconds = divmod(
473
+ self._timestamp, definitions.NANOSECONDS_PER_SECOND
474
+ )
475
+ number_of_days, hours, minutes, seconds = self._GetTimeValues(timestamp)
476
+
477
+ year, month, day_of_month = self._GetDateValuesWithEpoch(
478
+ number_of_days, self._EPOCH
479
+ )
480
+ return (
481
+ f"{year:04d}-{month:02d}-{day_of_month:02d} "
482
+ f"{hours:02d}:{minutes:02d}:{seconds:02d}.{nanoseconds:09d}"
483
+ )
484
+
485
+ def CopyToSerializableDict(self):
486
+ """Copies the date time value to a serializable dictionary.
487
+
488
+ Returns:
489
+ dict[str, object]: serializable dictionary.
490
+ """
491
+ serializable_dict = self._CreateSerializableDict()
492
+
493
+ serializable_dict["timestamp"] = self._timestamp
494
+
495
+ return serializable_dict
496
+
497
+
498
+ factory.Factory.RegisterDateTimeValues(PosixTime)
499
+ factory.Factory.RegisterDateTimeValues(PosixTimeInMilliseconds)
500
+ factory.Factory.RegisterDateTimeValues(PosixTimeInMicroseconds)
501
+ factory.Factory.RegisterDateTimeValues(PosixTimeInNanoseconds)