Suretime
Map nonstandard timezones to IANA zones on all platforms.
Record timestamps and intervals that behave correctly,
even if the timezone changes in the middle of a calculation.
pip install suretime tzdata
.
Timezone mapping
To get the local zone in IANA:
from suretime import Suretime, datetime
datetime.now().tzname()
Suretime.zones.first_local()
To map a nonstandard zone from elsewhere:
from suretime import Suretime
Suretime.zones.only("Europe/Tiraspol")
Suretime.zones.first("Central Pacific Standard Time")
Suretime.zones.first("Central Pacific Standard Time", territory="AQ")
Note that there is no 1-1 mapping between Windows and IANA timezones,
so suretime can fail despite its name.
"Tagged" datetimes and intervals
Suretime also has models to represent timestamps and intervals as accurately as the system permits.
For example, a TaggedInterval
contains the wall time, IANA zone, original (unmapped) timezone info
from the system, monotonic (typically boottime) clock time, and the clock used.
Timezone-resolved datetimes and intervals know both real and calendar times, correctly representing
the ground truth even if a timezone shift occurs between events – such as from a daylight savings change
or the user boarding a flight.
from suretime import Suretime
tagged = Suretime.tagged.now()
tagged.to_utc
tagged.clock.name
tagged == tagged
tagged.iso_with_zone
tzlocal is a bit different. It:
- ... only handles your current system’s timezone
- ... is highly OS-specific
- ... requires many system calls, making it typically much slower
- ... is compatible with Windows 2000, XP, and 7 and below
- ... is compatible with Python 3.6, 3.7, and 3.8
- ... very rarely, can access timezones on incorrectly configured POSIX systems
You can combine both packages, falling back to tzlocal if suretime fails.
(See the example below).
Full example
from suretime import Suretime, datetime
system_time = datetime.now().astimezone()
system_timezone = system_time.tzname()
Suretime.zones.only_local()
Suretime.zones.first(system_timezone)
Suretime.zones.only("America/Los_Angeles")
Suretime.zones.all("Central Pacific Standard Time")
Suretime.zones.all("Central Pacific Standard Time", "AQ")
Suretime.zones.first("Central Pacific Standard Time", "AQ")
Suretime.zones.first("nonexistent zone")
Suretime.zones.only("nonexistent zone")
Suretime.zones.only("Central Pacific Standard Time", "any")
tagged = Suretime.tagged.now_local_sys()
print(tagged.clock.name)
tagged = Suretime.tagged.now_local_ntp(server="north-america", kind="server-received")
tagged = Suretime.tagged.now_utc_ntp()
tagged = Suretime.tagged.now_local_sys()
print(tagged.clock.name)
print(tagged.clock.info.resolution)
print(tagged.iso_with_zone)
print(tagged.source.territory)
Suretime.clocks.sys()
Suretime.clocks.ntp()
ntp_data = Suretime.clocks.ntp_raw()
print(ntp_data.root_dispersion)
print(ntp_data.server_sent, ntp_data.client_received)
print(ntp_data.round_trip.total_seconds())
tagged = Suretime.tagged.now_utc_sys()
sys_now = Suretime.clocks.sys()
tagged.at(sys_now)
print(tagged < tagged)
print(tagged == tagged)
print(tagged == system_time)
print(tagged.is_identical_to(tagged))
then = Suretime.tagged.now()
for i in list(range(10000)): i += 1
now = Suretime.tagged.now()
interval = Suretime.tagged.interval(then, now)
print(interval.real_delta)
print(interval.wall_delta)
print(interval.iso)
print(interval.real_str)
print(interval.duration.iso)
import tzlocal
def get_local() -> Suretime.Types.TaggedDatetime:
try:
return Suretime.tagged.now()
except Suretime.Errors.CannotMapTzError:
zone = tzlocal.get_localzone()
return Suretime.tagged.exact(datetime.now(zone))
🍁 Contributing
Licensed under the terms of the Apache License 2.0.
New issues and pull requests are welcome.
Please refer to the contributing guide
and security policy.
Generated with Tyrannosaurus.