{ "info": { "author": "SecurActive SA", "author_email": "opensource@securactive.net", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Programming Language :: Python", "Topic :: Software Development", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": ".. :doctest:\n\nThis packages provides a time abstraction mecanism, allowing code that would\nuse it as reference to be diverted both on the local time zone and the real\ntime.\n\nThis allows clock-dependent code to be tested. See Getting started section for\na more thorough explanation.\n\nAdditionnaly, as an abstraction of the legacy datetime object, Time object\nprovided in ``sact.epoch.Time`` provides some common helpers and force this\nobject to always provide a timezone.\n\n``sact.epoch`` objects will be of some help:\n\n- if your application manage 2+ different timezones (ie: UTC and local\n timezone), and you are tired of legacy \"naive\" datetime object on this matter.\n\n- if you want to be able to divert system calls to local time, or\n local time zone of your application for test purpose.\n\n\nContents\n--------\n\nTime\n\n subclass of ``datetime``, represent an absolute instant of time (with\n timezone). It forces ``datetime`` usage to be aware of the\n timezone. Additionally, Time.now() will ask the Zope Component Architecture\n registry for a Clock Utility to provide the real time.\n\nClock\n\n Clock objects are general reference for getting Time object. The default\n clock is our common normal clock, but ZCA allows to substiture the reference\n and provide other type of Clock as ``sact.epoch.ManageableClock`` which can\n be managed (this means it can be stopped, set, translated in the future or\n the past).\n\nTimeZone\n\n TimeZone objects represents a specific timezone, ``sact.epoch.TzLocal()``\n will get the local system time zone. This call can be diverted also via the\n ZCA to provide another TimeZone. ``sact.epoch.testTimeZone`` is a common\n divert target timezone that is provided to help testing code.\n\n\nGetting started\n---------------\n\n``sact.epoch.Time`` is meant as a replacement of ``datetime.datetime``. As a\nsubclass of this later one, it'll provide the same functionality, and thus can\nbe used almost anywhere you are using ``datetime.datetime``.\n\nAdditionaly, using ``sact.epoch.Time`` ensures that:\n\n- all instances will get a time zone. Which isn't the case for ``datetime``\n objects.\n\n- ``.now()`` method will use the Zope Component Architecture registry to get\n a common Utility that is in charge of giving the real time. This allows\n simple overriding mecanism.\n\n\nGet timestamp from a datetime\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nLet's say you have some code using ``datetime.datetime.now()``::\n\n >>> import datetime\n >>> now = datetime.datetime.now()\n\nFirst issue: if this variable is meant to represent a time stored as UTC in a\ndatabase.\n\nHow do you get UTC timestamp from datetime ? (cf:\nhttp://bugs.python.org/issue1457227)\n\nThis is a common question. (cf:\nhttp://stackoverflow.com/questions/5067218/get-utc-timestamp-in-python-with-datetime/5499906#5499906)\n\nThe answer is ``datetime.datetime`` objects can be naive, which means unaware\nof the timezone. Thus, it is impossible to get UTC timestamp from this form of\ndatetime unless you can guess the timezone yourself.\n\nHopefully, the timezone of your system didn't change between the datetime\nobject creation and the moment you want to get a timestamp, if this is the case\nyou can safely use::\n\n >>> import sact.epoch.utils\n >>> utc_timestamp = sact.epoch.utils.dt2ts(now)\n\n``dt2ts`` will ask your system for the number of seconds between EPOCH\nin the current timezone and the provided datetime. This is why you\nmust ensure that datetime object was created when the same TimeZone on\nthe system than when you run this function.\n\nNo doctest is given to your eyes on the content of the variable\n``utc_timestamp`` because the output depends on the current time. And this\ncan be often an issue you'll encounter: having complex code that depends on\nthe current date, how do you test it ? This is the purpose of sact.epoch.Time.\n\n\nForcing to use only aware datetime\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nQuite quickly, you'll ask yourself: but what use have I of naive\n``datetime.datetime`` objects if they can't be used in lots of cases ?\n\nThe answer is: there are no use of naive ``datetime.datetime``.\n\nAware datetime objects as ``sact.epoch.Time`` contains all additional\ninformation allowing to:\n\n- get an UTC timestamp\n- compare two ``Time`` object whatever there timezone is.\n\nUsing naive datetime might even be concidered\nharmfull. ``sact.epoch.Time`` will ensure that all your objects are\ntimezone aware. By default, TimeZone won't even be dependent of your\nsystem local time, but will be stored in UTC timezone.\n\ndatetime objects::\n\n >>> from __future__ import print_function\n\n >>> print(repr(datetime.datetime.now().tzinfo))\n None\n >>> print(repr(datetime.datetime(1970, 1, 1, 1, 1).tzinfo))\n None\n\nIn comparison, ``sact.epoch.Time`` object will always set a timezone::\n\n >>> print(repr(sact.epoch.Time.now().tzinfo))\n \n >>> print(repr(sact.epoch.Time(1970, 1, 1, 1, 1).tzinfo))\n \n\nOf course, as Time object is aware, a simple ``timestamp`` property is\navailable::\n\n >>> epoch = sact.epoch.Time(1970, 1, 1, 0, 0)\n >>> epoch.timestamp\n 0\n\n\nDiverting time\n~~~~~~~~~~~~~~\n\nIf you use ``sact.epoch.Time.now()`` in place of\n``datetime.datetime.now()``, your code will have seams to divert real\ntime reference without touching the system clock.\n\nSay your code is::\n\n >>> db_timestamp = epoch.timestamp\n >>> def is_it_ok():\n ... now = sact.epoch.Time.now().timestamp\n ... print(0 == ((now - db_timestamp) % 2))\n\n``is_it_ok`` function code should print ``True`` if number of seconds between\nnow and epoch is odd.\n\nThis is the type of function which is quite difficult to test if you are using\n``datetime.datetime.now()``. Whole application will make extensive usage of the\nsystem clock, and will eventually be difficult to test unless you used\n``sact.epoch.Time.now()`` in place of datetime.\n\nHere's the test of the function::\n\n >>> clock = sact.epoch.clock.ManageableClock()\n\nBy default, the clock is following the system clock. Let's stop it and set it\nto epoch (more on manageable clock in the docstring of the class\nManageableClock)::\n\n >>> clock.stop()\n >>> clock.ts = 0\n\nNow let's use ZCA to declare this clock as new reference clock::\n\n >>> from zope.component import globalSiteManager as gsm\n >>> gsm.registerUtility(clock)\n\nWe are ready to test the function::\n\n >>> sact.epoch.Time.now().timestamp\n 0\n >>> is_it_ok()\n True\n\n >>> clock.ts = 1\n >>> sact.epoch.Time.now().timestamp\n 1\n >>> is_it_ok()\n False\n\nPlease note that ``ManageableClock`` have a ``wait`` method::\n\n >>> clock.wait(minutes=1)\n >>> sact.epoch.Time.now().timestamp\n 61\n >>> is_it_ok()\n False\n\nOf course, the execution of ``clock.wait`` is immediate. You can use a\n``datetime.timedelta`` as argument of wait or any keyword args you would send\nto ``datetime.timedelta`` constructor (this includes ``days``, ``seconds``,\n``microseconds``, ``milliseconds``, ``minutes``, ``hours``, ``weeks`` as of\npython version 2.7.1, cf:\nhttp://docs.python.org/library/datetime.html#datetime.timedelta)\n\n\nDiverting timezone of system\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWhen displaying times to the user, it is appreciated to show the time in local\ntimezone::\n\n >>> def what_time_is_it():\n ... print(sact.epoch.Time.now().local.iso)\n\nNotice the use of the property ``local`` which returns a new ``Time``\ninstance set to the same moment in time but in the system local\ntimezone, and the ``iso`` property which returns the iso string \nrepresentation of the ``Time`` object.\n\nThe ``local`` property uses ``sact.epoch.TzLocal()`` which is responsible of giving\nthe system local timezone:\n\n >>> sact.epoch.TzLocal()\n \n\nLet use the ZCA to divert the TzLocal mechanism to get the system local::\n\n >>> from sact.epoch import testTimeZone\n >>> from sact.epoch.interfaces import ITimeZone\n\n >>> gsm.registerUtility(testTimeZone, ITimeZone, name='local')\n\nNow we can test our function::\n\n >>> clock.ts = 0\n >>> what_time_is_it()\n 1970-01-01 00:05:00+00:05\n\nThe testTimeZone used is very special and recognizable on purpose: it has\na constant +5 minute offset on UTC.\n\nInternally, call to ``TzLocal()`` has been diverted::\n\n >>> sact.epoch.TzLocal()\n ", "description_content_type": null, "docs_url": "https://pythonhosted.org/sact.epoch/", "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/securactive/sact.epoch", "keywords": "sact time timedelta", "license": "BSD License", "maintainer": null, "maintainer_email": null, "name": "sact.epoch", "package_url": "https://pypi.org/project/sact.epoch/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/sact.epoch/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/securactive/sact.epoch" }, "release_url": "https://pypi.org/project/sact.epoch/1.3.0/", "requires_dist": null, "requires_python": null, "summary": "Time object subclassing datetime allowing diverting local clock mecanism", "version": "1.3.0" }, "last_serial": 1388859, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "027b2729069b46185178cf2709a6841b", "sha256": "41c3d72ca928034763ce53779ebbf52910dbbdeca8aa1aa4faa628cc45f9faf8" }, "downloads": -1, "filename": "sact.epoch-1.0.0.tar.gz", "has_sig": false, "md5_digest": "027b2729069b46185178cf2709a6841b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23817, "upload_time": "2011-04-08T17:01:10", "url": "https://files.pythonhosted.org/packages/1d/0d/7840081a89ae72ab51264b983e98f3dc1236eaf20b89f4d798d42877ff1b/sact.epoch-1.0.0.tar.gz" } ], "1.0.1": [], "1.0.2": [ { "comment_text": "", "digests": { "md5": "4603ec53ec17728f145be36161b4afb7", "sha256": "79df42cad0d75898dc774234c0e1dbe7b5a0a01f8cd9552f96ca7f36dea5b22b" }, "downloads": -1, "filename": "sact.epoch-1.0.2.tar.gz", "has_sig": false, "md5_digest": "4603ec53ec17728f145be36161b4afb7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25668, "upload_time": "2011-06-23T13:24:05", "url": "https://files.pythonhosted.org/packages/9e/0e/b700ac7113e9deabacff402d15a3417c88068220fbde58d570787419e674/sact.epoch-1.0.2.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "ec9c1dd0f34470aa684d8bb2a6865a4c", "sha256": "6647aec37588013455e534fd66725f6c8741465181e653c3d101e9ea358b9534" }, "downloads": -1, "filename": "sact.epoch-1.2.0.tar.gz", "has_sig": false, "md5_digest": "ec9c1dd0f34470aa684d8bb2a6865a4c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34905, "upload_time": "2014-12-30T11:36:18", "url": "https://files.pythonhosted.org/packages/f2/9d/dabb8385d9b64656fc433e507709a1e153b56b87395cee14418259312ba5/sact.epoch-1.2.0.tar.gz" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "7fb7b51d28121877b7b9eb0f2aa6031b", "sha256": "69d112a9b2faa717ffed3106dd7e1ba3d441f22b030a9a682e8ef81655ca0401" }, "downloads": -1, "filename": "sact.epoch-1.3.0.tar.gz", "has_sig": false, "md5_digest": "7fb7b51d28121877b7b9eb0f2aa6031b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36587, "upload_time": "2015-01-20T07:48:45", "url": "https://files.pythonhosted.org/packages/28/6e/710bb96d2fa9a17c814ab9e19ff1d7d9709c73fe20c565844d35cbe94fd1/sact.epoch-1.3.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "7fb7b51d28121877b7b9eb0f2aa6031b", "sha256": "69d112a9b2faa717ffed3106dd7e1ba3d441f22b030a9a682e8ef81655ca0401" }, "downloads": -1, "filename": "sact.epoch-1.3.0.tar.gz", "has_sig": false, "md5_digest": "7fb7b51d28121877b7b9eb0f2aa6031b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36587, "upload_time": "2015-01-20T07:48:45", "url": "https://files.pythonhosted.org/packages/28/6e/710bb96d2fa9a17c814ab9e19ff1d7d9709c73fe20c565844d35cbe94fd1/sact.epoch-1.3.0.tar.gz" } ] }