OLD | NEW |
(Empty) | |
| 1 Metadata-Version: 1.1 |
| 2 Name: strict-rfc3339 |
| 3 Version: 0.7 |
| 4 Summary: Strict, simple, lightweight RFC3339 functions |
| 5 Home-page: http://www.danielrichman.co.uk/libraries/strict-rfc3339.html |
| 6 Author: Daniel Richman, Adam Greig |
| 7 Author-email: main@danielrichman.co.uk |
| 8 License: GNU General Public License Version 3 |
| 9 Description: Strict, simple, lightweight RFC3339 functions |
| 10 ============================================= |
| 11 |
| 12 Goals |
| 13 ----- |
| 14 |
| 15 - Convert unix timestamps to and from RFC3339. |
| 16 - Either produce RFC3339 strings with a UTC offset (Z) or with the offs
et |
| 17 that the C time module reports is the local timezone offset. |
| 18 - Simple with minimal dependencies/libraries. |
| 19 - Avoid timezones as much as possible. |
| 20 - Be very strict and follow RFC3339. |
| 21 |
| 22 Caveats |
| 23 ------- |
| 24 |
| 25 - Leap seconds are not quite supported, since timestamps do not support
them, |
| 26 and it requires access to timezone data. |
| 27 - You may be limited by the size of `time_t` on 32 bit systems. |
| 28 |
| 29 In both cases, see 'Notes' below. |
| 30 |
| 31 Rationale |
| 32 --------- |
| 33 |
| 34 - A lot of libraries have trouble with DST transitions and ambiguous ti
mes. |
| 35 - Generally, using the python datetime object causes trouble, introduci
ng |
| 36 problems with timezones. |
| 37 - The excellent `pytz` library seems to achieve timezone perfection, ho
wever |
| 38 it didn't (at the time of writing) have a method for getting the loca
l |
| 39 timezone or the 'now' time in the local zone. |
| 40 - I saw a lot of problems ultimately due to information lost when conve
rting |
| 41 or transferring between two libraries (e.g., `time` -> `datetime` los
es DST |
| 42 info in the tuple) |
| 43 |
| 44 Usage |
| 45 ----- |
| 46 |
| 47 Validation: |
| 48 |
| 49 >>> strict_rfc3339.validate_rfc3339("some rubbish") |
| 50 False |
| 51 >>> strict_rfc3339.validate_rfc3339("2013-03-25T12:42:31+00:32") |
| 52 True |
| 53 |
| 54 Indeed, we can then: |
| 55 |
| 56 >>> strict_rfc3339.rfc3339_to_timestamp("2013-03-25T12:42:31+00:32") |
| 57 1364213431 |
| 58 >>> tuple(time.gmtime(1364213431))[:6] |
| 59 (2013, 3, 25, 12, 10, 31) |
| 60 |
| 61 No need for two function calls: |
| 62 |
| 63 >>> strict_rfc3339.rfc3339_to_timestamp("some rubbish") |
| 64 Traceback [...] |
| 65 strict_rfc3339.InvalidRFC3339Error |
| 66 |
| 67 Producing strings (for this example `TZ=America/New_York`): |
| 68 |
| 69 >>> strict_rfc3339.timestamp_to_rfc3339_utcoffset(1364213431) |
| 70 '2013-03-25T12:10:31Z' |
| 71 >>> strict_rfc3339.timestamp_to_rfc3339_localoffset(1364213431) |
| 72 '2013-03-25T08:10:31-04:00' |
| 73 |
| 74 And with `TZ=Europe/London`: |
| 75 |
| 76 >>> strict_rfc3339.timestamp_to_rfc3339_localoffset(1364213431) |
| 77 '2013-03-25T12:10:31+00:00' |
| 78 |
| 79 Convenience functions: |
| 80 |
| 81 >>> strict_rfc3339.now_to_rfc3339_utcoffset() |
| 82 '2013-03-25T21:39:35Z' |
| 83 >>> strict_rfc3339.now_to_rfc3339_localoffset() |
| 84 '2013-03-25T17:39:39-04:00' |
| 85 |
| 86 Floats: |
| 87 |
| 88 >>> strict_rfc3339.now_to_rfc3339_utcoffset(integer=True) # The defa
ult |
| 89 '2013-03-25T22:04:01Z' |
| 90 >>> strict_rfc3339.now_to_rfc3339_utcoffset(integer=False) |
| 91 '2013-03-25T22:04:01.04399Z' |
| 92 >>> strict_rfc3339.rfc3339_to_timestamp("2013-03-25T22:04:10.04399Z"
) |
| 93 1364249050.0439899 |
| 94 |
| 95 Behind the scenes |
| 96 ----------------- |
| 97 |
| 98 These functions are essentially string formatting and arithmetic only.
A very |
| 99 small number of functions do the heavy lifting. These come from two modu
les: |
| 100 `time` and `calendar`. |
| 101 |
| 102 `time` is a thin wrapper around the C time functions. I'm working on the |
| 103 assumption that these are usually of high quality and are correct. From
the |
| 104 `time` module, `strict_rfc3339` uses: |
| 105 |
| 106 - `time`: (actually calls `gettimeofday`) to get the current timestamp
/ "now" |
| 107 - `gmtime`: splits a timestamp into a UTC time tuple |
| 108 - `localtime`: splits a timestamp into a local time tuple |
| 109 |
| 110 Based on the assumption that they are correct, we can use the difference |
| 111 between the values returned by `gmtime` and `localtime` to find the loca
l |
| 112 offset. As clunky as it sounds, it's far easier than using a fully fled
ged |
| 113 timezone library. |
| 114 |
| 115 `calendar` is implemented in python. From `calendar`, `strict_rfc3339` u
ses: |
| 116 |
| 117 - `timegm`: turns a UTC time tuple into a timestamp. This essentially j
ust |
| 118 multiplies each number in the tuple by the number of seconds in it. I
t does |
| 119 use `datetime.date` to work out the number of days between Jan 1 1970
and the |
| 120 Y-M-D in the tuple, but this is fine. It does not perform much valida
tion at |
| 121 all. |
| 122 - `monthrange`: gives the number of days in a (year, month). I checked
and |
| 123 (at least in my copy of python 2.6) the function used for leap years
is |
| 124 identical to the one specified in RFC3339 itself. |
| 125 |
| 126 Notes |
| 127 ----- |
| 128 |
| 129 - RFC3339 specifies an offset, not a timezone, and the difference is |
| 130 important. Timezones are evil. |
| 131 - It is perhaps simpler to think of a RFC3339 string as a human readabl
e |
| 132 method of specifying a moment in time (only). These functions merely
provide |
| 133 access to the one-to-many timestamp-to-RFC3339 mapping. |
| 134 - Timestamps don't support leap seconds: a day is always 86400 "long". |
| 135 Also, validating leap seconds is particularly fiddly, because not onl
y do |
| 136 you need some data, but it must be kept up to date. |
| 137 For this reason, `strict_rfc3339` does not support leap seconds: in v
alidation, |
| 138 `seconds == 60` or `seconds == 61` is rejected. |
| 139 In the case of reverse leap seconds, calendar.timegm will blissfully
accept |
| 140 it. The result would be about as correct as you could get. |
| 141 - RFC3339 generation using `gmtime` or `localtime` may be limited by th
e size |
| 142 of `time_t` on the system: if it is 32 bit, you're limited to dates b
etween |
| 143 (approx) 1901 and 2038. This does not affect `rfc3339_to_timestamp`. |
| 144 |
| 145 Platform: UNKNOWN |
| 146 Classifier: Development Status :: 4 - Beta |
| 147 Classifier: Intended Audience :: Developers |
| 148 Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) |
| 149 Classifier: Operating System :: OS Independent |
| 150 Classifier: Programming Language :: Python |
| 151 Classifier: Programming Language :: Python :: 2 |
| 152 Classifier: Programming Language :: Python :: 3 |
OLD | NEW |