Skip to main content

A drop-in replacement for native datetimes that embraces UTC

Project description

****
zulu
****

|version| |travis| |coveralls| |license|


A drop-in replacement for native datetimes that embraces UTC


Links
=====

- Project: https://github.com/dgilland/zulu
- Documentation: https://zulu.readthedocs.io
- PyPI: https://pypi.python.org/pypi/zulu/
- TravisCI: https://travis-ci.org/dgilland/zulu


Features
========

- Supported on Python 2.7 and Python 3.4+
- 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.


Quickstart
==========

Install using pip:


::

pip install zulu


.. code-block:: python

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.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.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.delta('1w 3d 2h 32m')
# <Delta [10 days, 2:32:00]>

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

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


Why Zulu?
=========

Why zulu instead of `native datetimes <https://docs.python.org/3.5/library/datetime.html#datetime-objects>`_:

- Zulu has extended datetime features such as ``parse()``, ``format()``, ``shift()``, and `pytz <http://pytz.sourceforge.net/>`_ 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 <http://www.unicode.org/reports/tr35/tr35-19.html#Date_Field_Symbol_Table>`_ as well as ``strptime/strftime`` directives.


Why zulu instead of `Arrow <https://arrow.readthedocs.io>`_:

- 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 <http://www.unicode.org/reports/tr35/tr35-19.html#Date_Field_Symbol_Table>`_ 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:

- `Babel <https://github.com/python-babel/babel>`_
- `iso8601 <https://bitbucket.org/micktwomey/pyiso8601>`_
- `python-dateutil <https://github.com/dateutil/dateutil>`_
- `pytimeparse <https://github.com/wroberts/pytimeparse>`_
- `pytz <http://pythonhosted.org/pytz>`_
- `tzlocal <https://github.com/regebro/tzlocal>`_


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



.. |version| image:: https://img.shields.io/pypi/v/zulu.svg?style=flat-square
:target: https://pypi.python.org/pypi/zulu/

.. |travis| image:: https://img.shields.io/travis/dgilland/zulu/master.svg?style=flat-square
:target: https://travis-ci.org/dgilland/zulu

.. |coveralls| image:: https://img.shields.io/coveralls/dgilland/zulu/master.svg?style=flat-square
:target: https://coveralls.io/r/dgilland/zulu

.. |license| image:: https://img.shields.io/pypi/l/zulu.svg?style=flat-square
:target: https://pypi.python.org/pypi/zulu/


Changelog
=========


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 <http://www.unicode.org/reports/tr35/tr35-19.html#Date_Field_Symbol_Table>`_.
- 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.


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-0.4.0.tar.gz (34.7 kB view hashes)

Uploaded Source

Built Distribution

zulu-0.4.0-py2.py3-none-any.whl (20.6 kB view hashes)

Uploaded Python 2 Python 3

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