Index: third_party/google-endpoints/google/api/control/timestamp.py |
diff --git a/third_party/google-endpoints/google/api/control/timestamp.py b/third_party/google-endpoints/google/api/control/timestamp.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f013989a4504b9dd0459c28e7e1c255dfce4f9f6 |
--- /dev/null |
+++ b/third_party/google-endpoints/google/api/control/timestamp.py |
@@ -0,0 +1,133 @@ |
+# Copyright 2016 Google Inc. All Rights Reserved. |
+# |
+# Licensed under the Apache License, Version 2.0 (the "License"); |
+# you may not use this file except in compliance with the License. |
+# You may obtain a copy of the License at |
+# |
+# http://www.apache.org/licenses/LICENSE-2.0 |
+# |
+# Unless required by applicable law or agreed to in writing, software |
+# distributed under the License is distributed on an "AS IS" BASIS, |
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+# See the License for the specific language governing permissions and |
+# limitations under the License. |
+ |
+"""timestamp provides functions that support working with timestamps. |
+ |
+:func:`to_rfc3339` and :func:`from_rfc3339` convert between standard python |
+datetime types and the rfc3339 representation used in json messsages. |
+ |
+:func:`compare` allows comparison of any timestamp representation, either the |
+standard python datetime types, or an rfc3339 string representation |
+ |
+""" |
+ |
+from __future__ import absolute_import |
+ |
+import datetime |
+import logging |
+ |
+import strict_rfc3339 |
+ |
+logger = logging.getLogger(__name__) |
+ |
+ |
+_EPOCH_START = datetime.datetime(1970, 1, 1) |
+ |
+ |
+def compare(a, b): |
+ """Compares two timestamps. |
+ |
+ ``a`` and ``b`` must be the same type, in addition to normal |
+ representations of timestamps that order naturally, they can be rfc3339 |
+ formatted strings. |
+ |
+ Args: |
+ a (string|object): a timestamp |
+ b (string|object): another timestamp |
+ |
+ Returns: |
+ int: -1 if a < b, 0 if a == b or 1 if a > b |
+ |
+ Raises: |
+ ValueError: if a or b are not the same type |
+ ValueError: if a or b strings but not in valid rfc3339 format |
+ |
+ """ |
+ a_is_text = isinstance(a, basestring) |
+ b_is_text = isinstance(b, basestring) |
+ if type(a) != type(b) and not (a_is_text and b_is_text): |
+ logger.error('Cannot compare %s to %s, types differ %s!=%s', |
+ a, b, type(a), type(b)) |
+ raise ValueError('cannot compare inputs of differing types') |
+ |
+ if a_is_text: |
+ a = from_rfc3339(a, with_nanos=True) |
+ b = from_rfc3339(b, with_nanos=True) |
+ |
+ if a < b: |
+ return -1 |
+ elif a > b: |
+ return 1 |
+ else: |
+ return 0 |
+ |
+ |
+def to_rfc3339(timestamp): |
+ """Converts ``timestamp`` to an RFC 3339 date string format. |
+ |
+ ``timestamp`` can be either a ``datetime.datetime`` or a |
+ ``datetime.timedelta``. Instances of the later are assumed to be a delta |
+ with the beginining of the unix epoch, 1st of January, 1970 |
+ |
+ The returned string is always Z-normalized. Examples of the return format: |
+ '1972-01-01T10:00:20.021Z' |
+ |
+ Args: |
+ timestamp (datetime|timedelta): represents the timestamp to convert |
+ |
+ Returns: |
+ string: timestamp converted to a rfc3339 compliant string as above |
+ |
+ Raises: |
+ ValueError: if timestamp is not a datetime.datetime or datetime.timedelta |
+ |
+ """ |
+ if isinstance(timestamp, datetime.datetime): |
+ timestamp = timestamp - _EPOCH_START |
+ if not isinstance(timestamp, datetime.timedelta): |
+ logger.error('Could not convert %s to a rfc3339 time,', timestamp) |
+ raise ValueError('Invalid timestamp type') |
+ return strict_rfc3339.timestamp_to_rfc3339_utcoffset( |
+ timestamp.total_seconds()) |
+ |
+ |
+def from_rfc3339(rfc3339_text, with_nanos=False): |
+ """Parse a RFC 3339 date string format to datetime.date. |
+ |
+ Example of accepted format: '1972-01-01T10:00:20.021-05:00' |
+ |
+ - By default, the result is a datetime.datetime |
+ - If with_nanos is true, the result is a 2-tuple, (datetime.datetime, |
+ nanos), where the second field represents the possible nanosecond |
+ resolution component of the second field. |
+ |
+ Args: |
+ rfc3339_text (string): An rfc3339 formatted date string |
+ with_nanos (bool): Determines if nanoseconds should be parsed from the |
+ string |
+ |
+ Raises: |
+ ValueError: if ``rfc3339_text`` is invalid |
+ |
+ Returns: |
+ :class:`datetime.datetime`: when with_nanos is False |
+ tuple(:class:`datetime.datetime`, int): when with_nanos is True |
+ |
+ """ |
+ timestamp = strict_rfc3339.rfc3339_to_timestamp(rfc3339_text) |
+ result = datetime.datetime.utcfromtimestamp(timestamp) |
+ if with_nanos: |
+ return (result, int((timestamp - int(timestamp)) * 1e9)) |
+ else: |
+ return result |