Skip to main content

A drop-in replacement for native datetimes that embraces UTC

Project description

version build coveralls license

A drop-in replacement for native datetimes that embraces UTC

Features

  • All datetime objects converted and stored as UTC.

  • Parses ISO8601 formatted strings and POSIX timestamps by default.

  • Timezone representation applied only during string output formatting or when casting to native datetime object.

  • Drop-in replacement for native datetime objects.

  • Python 3.6+

Quickstart

Install using pip:

pip3 install zulu
import zulu

zulu.now()
# <Zulu [2016-07-25T19:33:18.137493+00:00]>

dt = zulu.parse('2016-07-25T19:33:18.137493+00:00')
# <Zulu [2016-07-25T19:33:18.137493+00:00]>

dt = zulu.create(2016, 7, 25, 19, 33, 18, 137493)
# <Zulu [2016-07-25T19:33:18.137493+00:00]>

dt.isoformat()
# '2016-07-25T19:33:18.137493+00:00'

dt.timestamp()
# 1469475198.137493

dt.naive
# datetime.datetime(2016, 7, 25, 19, 33, 18, 137493)

dt.datetime
# datetime.datetime(2016, 7, 25, 19, 33, 18, 137493, tzinfo=<UTC>)

dt.format('%Y-%m-%d')
# 2016-07-25

dt.format('YYYY-MM-dd')
# 2016-07-25

dt.format("E, MMM d, ''YY")
# "Mon, Jul 25, '16"

dt.format("E, MMM d, ''YY", locale='de')
# "Mo., Juli 25, '16"

dt.format("E, MMM d, ''YY", locale='fr')
# "lun., juil. 25, '16"

dt.shift(hours=-5, minutes=10)
# <Zulu [2016-07-25T14:43:18.137493+00:00]>

dt.replace(hour=14, minute=43)
# <Zulu [2016-07-25T14:43:18.137493+00:00]>

dt.start_of('day')
# <Zulu [2016-07-25T00:00:00+00:00]>

dt.end_of('day')
# <Zulu [2016-07-25T23:59:59.999999+00:00]>

dt.span('hour')
# (<Zulu [2016-07-25T19:00:00+00:00]>, <Zulu [2016-07-25T19:59:59.999999+00:00]>)

dt.time_from(dt.end_of('day'))
# '4 hours ago'

dt.time_to(dt.end_of('day'))
# 'in 4 hours'

list(zulu.range('hour', dt, dt.shift(hours=4)))
# [Zulu [2016-07-25T19:33:18.137493+00:00]>,
#  Zulu [2016-07-25T20:33:18.137493+00:00]>,
#  Zulu [2016-07-25T21:33:18.137493+00:00]>,
#  Zulu [2016-07-25T22:33:18.137493+00:00]>]

list(zulu.span_range('minute', dt, dt.shift(minutes=4)))
# [(Zulu [2016-07-25T19:33:00+00:00]>, Zulu [2016-07-25T19:33:59.999999+00:00]>),
#  (Zulu [2016-07-25T19:34:00+00:00]>, Zulu [2016-07-25T19:34:59.999999+00:00]>),
#  (Zulu [2016-07-25T19:35:00+00:00]>, Zulu [2016-07-25T19:35:59.999999+00:00]>),
#  (Zulu [2016-07-25T19:36:00+00:00]>, Zulu [2016-07-25T19:36:59.999999+00:00]>)]

zulu.parse_delta('1w 3d 2h 32m')
# <Delta [10 days, 2:32:00]>

zulu.parse_delta('2:04:13:02.266')
# <Delta [2 days, 4:13:02.266000]>

zulu.parse_delta('2 days, 5 hours, 34 minutes, 56 seconds')
# <Delta [2 days, 5:34:56]>

Why Zulu?

Why zulu instead of native datetimes:

  • Zulu has extended datetime features such as parse(), format(), shift(), and python-dateutil timezone support.

  • Parses ISO8601 and timestamps by default without any extra arguments.

  • Easier to reason about Zulu objects since they are only ever UTC datetimes.

  • Clear delineation between UTC and other time zones where timezone representation is only applicable for display or conversion to native datetime.

  • Supports more string parsing/formatting options using Unicode date patterns as well as strptime/strftime directives.

Why zulu instead of Arrow:

  • Zulu is a drop-in replacement for native datetimes (inherits from datetime.datetime). No need to convert using arrow.datetime when you need a datetime (zulu is always a datetime).

  • Stricter parsing to avoid silent errors. For example, one might expect arrow.get('02/08/1987', 'MM/DD/YY') to fail (input does not match format) but it gladly returns <Arrow [2019-02-08T00:00:00+00:00) whereas zulu.parse('02/08/1987', '%m/%d/%y') throws zulu.parser.ParseError: Value "02/08/1987" does not match any format in ['%m/%d/%y'].

  • Avoids timezone/DST shifting bugs by only dealing with UTC datetimes when applying timedeltas or performing other calculations.

  • Supports strptime/strftime as well as Unicode date patterns for string parsing/formatting.

Special Thanks

Special thanks goes out to the authors/contributors of the following libraries that have made it possible for zulu to exist:

For the full documentation, please visit https://zulu.readthedocs.io.

Changelog

v2.0.1 (2023-11-20)

  • Add support for Python 3.12

  • Replace usage of deprecated datetime.utcnow and datetime.utcfromtimestamp.

v2.0.0 (2021-06-26)

  • Drop support for Python 3.4 and 3.5.

v1.3.1 (2021-06-26)

  • Fix compatibility issue with Python 3.4 and 3.5 by replacing f-string usage with string-format.

v1.3.0 (2021-01-07)

  • Add Python 3.9 support.

  • Fix bug in Zulu.time_from, Zulu.time_to, Zulu.time_from_now, and Zulu.time_to_now where keyword arguments weren’t passed to underlying Delta.format call.

  • Fix bug in Zulu.format where “YY” and “YYYY” format patterns would return the year in “Week of Year” based calendars instead of the regular calendar year.

v1.2.0 (2020-01-14)

  • Add Python 3.8 support.

  • Add 'week' option to Zulu.start_of, Zulu.end_of, Zulu.span, and Zulu.span_range. Thanks ThomasChiroux!

  • Fix bug in Zulu.astimezone in Python 3.8 due to change in return type from super().asdatetime. In Python<=3.7, super().asdatetime returned as instance of datetime, but in Python 3.8 another instance of Zulu was returned instead. Zulu.astimezone will now return a datetime instance in Python 3.8.

v1.1.1 (2019-08-14)

  • Remove unused parameter in zulu.Timer.__init__().

v1.1.0 (2018-11-01)

  • Add fold attribute support to Zulu.

  • Add zulu.to_seconds for converting units of time to total number of seconds.

  • Add zulu.Timer class that can be used to track elapsed time (like a stopwatch) or as a countdown timer.

v1.0.0 (2018-08-20)

  • Drop support for Python 2.7.

v0.12.1 (2018-07-16)

  • Support Python 3.7.

v0.12.0 (2017-07-11)

  • Add Zulu.datetimetuple().

  • Add Zulu.datetuple().

  • Remove Zulu.__iter__ method. (breaking change)

  • Remove Delta.__iter__ method. (breaking change)

v0.11.0 (2017-06-28)

  • Add Python 3.6 support.

  • Add Delta.__iter__ method that yields 2-element tuples like Zulu.__iter__. Delta values are normalized into integer values distributed from the higher units to the lower units.

  • Add Delta.__float__ and Delta.__int__ methods for converting to seconds.

  • Add Zulu.__float__ and Zulu.__int__ methods for converting to epoch seconds.

  • Fix issue in Python 3.6 where zulu.now() returned a naive datetime Zulu instance.

  • Make Zulu.__iter__ yield 2-element tuples containing (unit, value) like (('year', 2000), ('month', 12), ...) so it can be converted to a dict with proper keys easier. (breaking change)

  • Remove previously deprecated zulu.delta() function. Use zulu.parse_delta() instead. (breaking change)

  • Rename modules: (breaking change)

    • zulu.datetime -> zulu.zulu

    • zulu.timedelta -> zulu.delta

v0.10.1 (2017-02-15)

  • Provide fallback for the default value of locale in Delta.format() when a locale is not known via environment variables.

v0.10.0 (2017-02-13)

  • Add zulu.parse_delta as alias for Delta.parse.

  • Deprecate zulu.delta in favor of zulu.parse_delta.

  • Allow first argument to Zulu(), Zulu.parse(), and zulu.parse() to be a dict containing keys corresponding to initialization parameters.

  • Fix error message for invalid timezone strings so that the supplied string is shown correctly.

v0.9.0 (2016-11-21)

  • Require python-dateutil>=2.6.0. (breaking change)

  • Replace usage of pytz timezone handling for strings with dateutil.tz.gettz. Continue to support pytz timezones during Zulu() object creation. (breaking change).

  • Replace default UTC timezone with dateutil.tz.tzutc(). Was previously pytz.UTC. (breaking change)

  • Replace local timezone with dateutil.tz.tzlocal(). Was previously set by the tzlocal library. (breaking change)

v0.8.0 (2016-10-31)

  • Add comparison methods to Zulu:

    • is_before

    • is_on_or_before

    • is_after

    • is_on_or_after

    • is_between

v0.7.3 (2016-10-24)

  • Optimize Zulu() constructor by eliminating multiple unnecessary calls to datetime constructor.

v0.7.2 (2016-09-06)

  • Fix Zulu not being pickle-able.

v0.7.1 (2016-08-22)

  • Add missing magic method overrides for Delta for +delta, -delta, and abs(delta) so that Delta is returned instead of datetime.timedelta.

    • __pos__

    • __neg__

    • __abs__

v0.7.0 (2016-08-22)

  • Make Zulu.__sub__ and Zulu.subtract return a Delta object instead of datetime.timedelta.

  • Make zulu.delta and Zulu.Delta.parse accept a number.

  • Allow the first argument to Zulu.shift be a timedelta or relative delta object.

  • Ensure that mathematical magic methods for Delta return Delta objects and not datetime.timedelta.

    • __add__

    • __radd__

    • __sub__

    • __mul__

    • __rmul__

    • __floordiv__

    • __truediv__ (Python 3 only)

    • __div__ (Python 2 only)

    • __mod__ (Python 3 only)

    • __divmod__ (Python 3 only)

v0.6.0 (2016-08-14)

  • Replace internal implementation of Unicode date pattern formatting with Babel’s format_datetime. breaking change

  • Remove support for formatting to timestamp using X and XX. breaking change

  • Rename parse-from-timestamp token from X to timestamp. breaking change

  • Add zulu.create as factory function to create a zulu.Zulu instance.

  • Add locale support to Zulu.format when using Unicode date pattern format tokens.

  • Restore locale support to Delta.format.

v0.5.0 (2016-08-13)

  • Remove locale support from Delta.format. Locale is currently not supported in Zulu.format so decided to disable it in Delta.format until both can have it. breaking change

v0.4.0 (2016-08-13)

  • Rename zulu.DateTime to zulu.Zulu. breaking change

  • Rename Zulu.isleap to Zulu.is_leap_year. breaking change

  • Remove zulu.format alias (function can be accessed at zulu.parser.format_datetime). breaking change

  • Remove Zulu.leapdays. breaking change

  • Add Zulu.days_in_month.

  • Add zulu.Delta class that inherits from datetime.timedelta.

  • Add zulu.delta as alias to zulu.Delta.parse.

  • Add Zulu.time_from, Zulu.time_to, Zulu.time_from_now, and Zulu.time_to_now that return “time ago” or “time to” humanized strings.

  • Add zulu.range as alias to Zulu.range.

  • Add zulu.span_range as alias to Zulu.span_range.

  • Make time units (years, months, weeks, days, hours, minutes, seconds, microseconds) keyword arguments only for Zulu.add/subtract, but allow positional argument to be an addable/subtractable object (datetime, timedelta, dateutil.relativedelta). breaking change

v0.3.0 (2016-08-03)

  • Rename DateTime.sub to DateTime.subtract. breaking change

  • Allow the first argument to DateTime.add to be a datetime.timedelta or dateutil.relativedelta object.

  • Allow the first argument to DateTime.subtract to be a DateTime, datetime.datetime, datetime.timedelta, or dateutil.relativedelta object.

  • Provide zulu.ISO8601 and zulu.TIMESTAMP as parse/format constants that can be used in zulu.parse(string, zulu.ISO8601) and DateTime.format(zulu.ISO8601).

  • Remove special parse format string 'timestamp' in favor of using just 'X' as defined in zulu.TIMESTAMP. breaking change

  • Import zulu.parser.format to zulu.format.

  • Fix bug in DateTime addition operation that resulted in a native datetime being returned instead of DateTime.

v0.2.0 (2016-08-02)

  • Add DateTime.datetime property that returns a native datetime.

  • Add DateTime.fromgmtime that creates a DateTime from a UTC based time.struct_time.

  • Add DateTime.fromlocaltime that creates a DateTime from a local time.struct_time.

  • Add DateTime.isleap method that returns whether its year is a leap year.

  • Add DateTime.leapdays that calculates the number of leap days between its year and another year.

  • Add DateTime.start_of/end_of and other variants that return the start of end of a time frame:

    • start/end_of_century

    • start/end_of_decade

    • start/end_of_year

    • start/end_of_month

    • start/end_of_day

    • start/end_of_hour

    • start/end_of_minute

    • start/end_of_second

  • Add DateTime.span that returns the start and end of a time frame.

  • Add DateTime.span_range that returns a range of spans.

  • Add DateTime.range that returns a range of datetimes.

  • Add DateTime.add and DateTime.sub methods.

  • Add years and months arguments to DateTime.shift/add/sub.

  • Drop support for milliseconds from DateTime.shift/add/sub. breaking change

  • Make DateTime.parse/format understand a subset of Unicode date patterns.

  • Set defaults for year (1970), month (1), and day (1) arguments to new DateTime objects. Creating a new DateTime now defaults to the start of the POSIX epoch.

v0.1.2 (2016-07-26)

  • Don’t pin install requirements to a specific version; use >= instead.

v0.1.1 (2016-07-26)

  • Fix bug in DateTime.naive that resulted in a DateTime object being returned instead of a native datetime.

v0.1.0 (2016-07-26)

  • First release.

MIT License

Copyright (c) 2020 Derrick Gilland

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zulu-2.0.1.tar.gz (49.1 kB view details)

Uploaded Source

Built Distribution

zulu-2.0.1-py3-none-any.whl (23.7 kB view details)

Uploaded Python 3

File details

Details for the file zulu-2.0.1.tar.gz.

File metadata

  • Download URL: zulu-2.0.1.tar.gz
  • Upload date:
  • Size: 49.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.12.0

File hashes

Hashes for zulu-2.0.1.tar.gz
Algorithm Hash digest
SHA256 d2241f66d19582d9da6f13522c5409e10abc350574e4e61de4c5287517698f5a
MD5 4423dc0881e135b9a9e92061ae87f488
BLAKE2b-256 3e464836fb9fbe0d8b5b76d41c2d19a56668e6e309a7b81a30841489f356e097

See more details on using hashes here.

File details

Details for the file zulu-2.0.1-py3-none-any.whl.

File metadata

  • Download URL: zulu-2.0.1-py3-none-any.whl
  • Upload date:
  • Size: 23.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.12.0

File hashes

Hashes for zulu-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 91366df8fa6d1306c9e399e304b4bbccd7a8375794479258b8a459302ec06701
MD5 4d1e1ee2d949d29de5641752c8a99402
BLAKE2b-256 7ce8635a8c91483c2549e31c9cc48c3842bae27ba37e6835abd033d456549b7e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page