# -*- coding: utf-8 -*-
"""
Module containing a UTC-based datetime class.
:copyright:
The ObsPy Development Team (devs@obspy.org)
:license:
GNU Lesser General Public License, Version 3
(https://www.gnu.org/copyleft/lesser.html)
"""
from __future__ import (absolute_import, division, print_function,
unicode_literals)
from future.builtins import * # NOQA @UnusedWildImport
from future.utils import native_str
import datetime
import math
import time
from obspy.core.util.decorator import deprecated
TIMESTAMP0 = datetime.datetime(1970, 1, 1, 0, 0)
[docs]class UTCDateTime(object):
"""
A UTC-based datetime object.
This datetime class is based on the POSIX time, a system for describing
instants in time, defined as the number of seconds elapsed since midnight
Coordinated Universal Time (UTC) of Thursday, January 1, 1970. Using a
single float timestamp allows higher precision as the default Python
:class:`datetime.datetime` class. It features the full `ISO8601:2004`_
specification and some additional string patterns during object
initialization.
:type args: int, float, str, :class:`datetime.datetime`, optional
:param args: The creation of a new `UTCDateTime` object depends from the
given input parameters. All possible options are summarized in the
`Examples`_ section below.
:type iso8601: bool, optional
:param iso8601: Enforce `ISO8601:2004`_ detection. Works only with a string
as first input argument.
:type precision: int, optional
:param precision: Sets the precision used by the rich comparison operators.
Defaults to ``6`` digits after the decimal point. See also `Precision`_
section below.
.. versionchanged:: 0.5.1
UTCDateTime is no longer based on Python's datetime.datetime class
instead uses timestamp as a single floating point value which allows
higher precision.
.. rubric:: Supported Operations
``UTCDateTime = UTCDateTime + delta``
Adds/removes ``delta`` seconds (given as int or float) to/from the
current ``UTCDateTime`` object and returns a new ``UTCDateTime``
object.
See also: :meth:`~obspy.core.utcdatetime.UTCDateTime.__add__`.
``delta = UTCDateTime - UTCDateTime``
Calculates the time difference in seconds between two ``UTCDateTime``
objects. The time difference is given as float data type and may also
contain a negative number.
See also: :meth:`~obspy.core.utcdatetime.UTCDateTime.__sub__`.
.. rubric:: _`Examples`
(1) Using a timestamp.
>>> UTCDateTime(0)
UTCDateTime(1970, 1, 1, 0, 0)
>>> UTCDateTime(1240561632)
UTCDateTime(2009, 4, 24, 8, 27, 12)
>>> UTCDateTime(1240561632.5)
UTCDateTime(2009, 4, 24, 8, 27, 12, 500000)
(2) Using a `ISO8601:2004`_ string. The detection may be enforced by
setting the ``iso8601`` parameter to True.
* Calendar date representation.
>>> UTCDateTime("2009-12-31T12:23:34.5")
UTCDateTime(2009, 12, 31, 12, 23, 34, 500000)
>>> UTCDateTime("20091231T122334.5") # compact
UTCDateTime(2009, 12, 31, 12, 23, 34, 500000)
>>> UTCDateTime("2009-12-31T12:23:34.5Z") # w/o time zone
UTCDateTime(2009, 12, 31, 12, 23, 34, 500000)
>>> UTCDateTime("2009-12-31T12:23:34+01:15") # w/ time zone
UTCDateTime(2009, 12, 31, 11, 8, 34)
* Ordinal date representation.
>>> UTCDateTime("2009-365T12:23:34.5")
UTCDateTime(2009, 12, 31, 12, 23, 34, 500000)
>>> UTCDateTime("2009365T122334.5") # compact
UTCDateTime(2009, 12, 31, 12, 23, 34, 500000)
>>> UTCDateTime("2009001", iso8601=True) # enforce ISO8601
UTCDateTime(2009, 1, 1, 0, 0)
* Week date representation.
>>> UTCDateTime("2009-W53-7T12:23:34.5")
UTCDateTime(2010, 1, 3, 12, 23, 34, 500000)
>>> UTCDateTime("2009W537T122334.5") # compact
UTCDateTime(2010, 1, 3, 12, 23, 34, 500000)
>>> UTCDateTime("2009W011", iso8601=True) # enforce ISO8601
UTCDateTime(2008, 12, 29, 0, 0)
(3) Using not ISO8601 compatible strings.
>>> UTCDateTime("1970-01-01 12:23:34")
UTCDateTime(1970, 1, 1, 12, 23, 34)
>>> UTCDateTime("1970,01,01,12:23:34")
UTCDateTime(1970, 1, 1, 12, 23, 34)
>>> UTCDateTime("1970,001,12:23:34")
UTCDateTime(1970, 1, 1, 12, 23, 34)
>>> UTCDateTime("20090701121212")
UTCDateTime(2009, 7, 1, 12, 12, 12)
>>> UTCDateTime("19700101")
UTCDateTime(1970, 1, 1, 0, 0)
>>> UTCDateTime("20110818_03:00:00")
UTCDateTime(2011, 8, 18, 3, 0)
(4) Using multiple arguments in the following order: `year, month,
day[, hour[, minute[, second[, microsecond]]]`. The year, month and day
arguments are required.
>>> UTCDateTime(1970, 1, 1)
UTCDateTime(1970, 1, 1, 0, 0)
>>> UTCDateTime(1970, 1, 1, 12, 23, 34, 123456)
UTCDateTime(1970, 1, 1, 12, 23, 34, 123456)
(5) Using the following keyword arguments: `year, month, day, julday, hour,
minute, second, microsecond`. Either the combination of year, month and
day, or year and Julian day are required.
>>> UTCDateTime(year=1970, month=1, day=1, minute=15, microsecond=20)
UTCDateTime(1970, 1, 1, 0, 15, 0, 20)
>>> UTCDateTime(year=2009, julday=234, hour=14, minute=13)
UTCDateTime(2009, 8, 22, 14, 13)
(6) Using a Python :class:`datetime.datetime` object.
>>> dt = datetime.datetime(2009, 5, 24, 8, 28, 12, 5001)
>>> UTCDateTime(dt)
UTCDateTime(2009, 5, 24, 8, 28, 12, 5001)
.. rubric:: _`Precision`
The :class:`UTCDateTime` class works with a default precision of ``6``
digits which effects the comparison of date/time values, e.g.:
>>> dt = UTCDateTime(0)
>>> dt2 = UTCDateTime(0.00001)
>>> dt3 = UTCDateTime(0.0000001)
>>> print(dt.precision)
6
>>> dt == dt2 # 5th digit is within current precision
False
>>> dt == dt3 # 7th digit will be neglected
True
You may change that behavior either by,
(1) using the ``precision`` keyword during object initialization:
>>> dt = UTCDateTime(0, precision=4)
>>> dt2 = UTCDateTime(0.00001, precision=4)
>>> print(dt.precision)
4
>>> dt == dt2
True
(2) or set it the class attribute ``DEFAULT_PRECISION`` for all new
:class:`UTCDateTime` objects using a monkey patch:
>>> UTCDateTime.DEFAULT_PRECISION = 4
>>> dt = UTCDateTime(0)
>>> dt2 = UTCDateTime(0.00001)
>>> print(dt.precision)
4
>>> dt == dt2
True
Don't forget to reset ``DEFAULT_PRECISION`` if not needed anymore!
>>> UTCDateTime.DEFAULT_PRECISION = 6
.. _ISO8601:2004: https://en.wikipedia.org/wiki/ISO_8601
"""
timestamp = 0.0
DEFAULT_PRECISION = 6
[docs] def __init__(self, *args, **kwargs):
"""
Creates a new UTCDateTime object.
"""
# set default precision
self.precision = kwargs.pop('precision', self.DEFAULT_PRECISION)
# iso8601 flag
iso8601 = kwargs.pop('iso8601', False) is True
# check parameter
if len(args) == 0 and len(kwargs) == 0:
# use current time if no time is given
self.timestamp = time.time()
return
elif len(args) == 1 and len(kwargs) == 0:
value = args[0]
# check types
try:
# got a timestamp
self.timestamp = value.__float__()
return
except:
pass
if isinstance(value, datetime.datetime):
# got a Python datetime.datetime object
self._from_datetime(value)
return
elif isinstance(value, datetime.date):
# got a Python datetime.date object
dt = datetime.datetime(value.year, value.month, value.day)
self._from_datetime(dt)
return
elif isinstance(value, (bytes, str)):
if not isinstance(value, (str, native_str)):
value = value.decode()
# got a string instance
value = value.strip()
# check for ISO8601 date string
if value.count("T") == 1 or iso8601:
try:
self.timestamp = self._parse_iso_8601(value).timestamp
return
except:
if iso8601:
raise
# try to apply some standard patterns
value = value.replace('T', ' ')
value = value.replace('_', ' ')
value = value.replace('-', ' ')
value = value.replace(':', ' ')
value = value.replace(',', ' ')
value = value.replace('Z', ' ')
value = value.replace('W', ' ')
# check for ordinal date (julian date)
parts = value.split(' ')
# check for patterns
if len(parts) == 1 and len(value) == 7 and value.isdigit():
# looks like an compact ordinal date string
pattern = "%Y%j"
elif len(parts) > 1 and len(parts[1]) == 3 and \
parts[1].isdigit():
# looks like an ordinal date string
value = ''.join(parts)
if len(parts) > 2:
pattern = "%Y%j%H%M%S"
else:
pattern = "%Y%j"
else:
# some parts should have 2 digits
for i in range(1, min(len(parts), 6)):
if len(parts[i]) == 1:
parts[i] = '0' + parts[i]
value = ''.join(parts)
# fill missing elements with zeros
value += '0' * (14 - len(value))
pattern = "%Y%m%d%H%M%S"
ms = 0
if '.' in value:
parts = value.split('.')
value = parts[0].strip()
try:
ms = float('.' + parts[1].strip())
except:
pass
# all parts should be digits now - here we filter unknown
# patterns and pass it directly to Python's datetime.datetime
if not ''.join(parts).isdigit():
dt = datetime.datetime(*args, **kwargs)
self._from_datetime(dt)
return
dt = datetime.datetime.strptime(value, pattern)
self._from_datetime(dt, ms)
return
# check for ordinal/julian date kwargs
if 'julday' in kwargs:
if 'year' in kwargs:
# year given as kwargs
year = kwargs['year']
elif len(args) == 1:
# year is first (and only) argument
year = args[0]
try:
temp = "%4d%03d" % (int(year),
int(kwargs['julday']))
dt = datetime.datetime.strptime(temp, '%Y%j')
except:
pass
else:
kwargs['month'] = dt.month
kwargs['day'] = dt.day
kwargs.pop('julday')
# check if seconds are given as float value
if len(args) == 6 and isinstance(args[5], float):
_frac, _sec = math.modf(round(args[5], 6))
kwargs['microsecond'] = int(round(_frac * 1e6))
kwargs['second'] = int(_sec)
args = args[0:5]
dt = datetime.datetime(*args, **kwargs)
self._from_datetime(dt)
[docs] def _set(self, **kwargs):
"""
Sets current timestamp using kwargs.
"""
year = kwargs.get('year', self.year)
month = kwargs.get('month', self.month)
day = kwargs.get('day', self.day)
hour = kwargs.get('hour', self.hour)
minute = kwargs.get('minute', self.minute)
second = kwargs.get('second', self.second)
microsecond = kwargs.get('microsecond', self.microsecond)
julday = kwargs.get('julday', None)
if julday:
self.timestamp = UTCDateTime(year=year, julday=julday, hour=hour,
minute=minute, second=second,
microsecond=microsecond).timestamp
else:
self.timestamp = UTCDateTime(year, month, day, hour, minute,
second, microsecond).timestamp
[docs] def _from_datetime(self, dt, ms=0):
"""
Use Python datetime object to set current time.
:type dt: :class:`datetime.datetime`
:param dt: Python datetime object.
:type ms: float
:param ms: extra seconds to add to current UTCDateTime object.
"""
# see datetime.timedelta.total_seconds
try:
td = (dt - TIMESTAMP0)
except TypeError:
td = (dt.replace(tzinfo=None) - dt.utcoffset()) - TIMESTAMP0
self.timestamp = (td.microseconds + (td.seconds + td.days * 86400) *
1000000) / 1000000.0 + ms
@staticmethod
[docs] def _parse_iso_8601(value):
"""
Parses an ISO8601:2004 date time string.
"""
# remove trailing 'Z'
value = value.replace('Z', '')
# split between date and time
try:
(date, time) = value.split("T")
except:
date = value
time = ""
# remove all hyphens in date
date = date.replace('-', '')
# remove colons in time
time = time.replace(':', '')
# guess date pattern
length_date = len(date)
if date.count('W') == 1 and length_date == 8:
# we got a week date: YYYYWwwD
# remove week indicator 'W'
date = date.replace('W', '')
date_pattern = "%Y%W%w"
year = int(date[0:4])
# [Www] is the week number prefixed by the letter 'W', from W01
# through W53.
# strpftime %W == Week number of the year (Monday as the first day
# of the week) as a decimal number [00,53]. All days in a new year
# preceding the first Monday are considered to be in week 0.
week = int(date[4:6]) - 1
# [D] is the weekday number, from 1 through 7, beginning with
# Monday and ending with Sunday.
# strpftime %w == Weekday as a decimal number [0(Sunday),6]
day = int(date[6])
if day == 7:
day = 0
date = "%04d%02d%1d" % (year, week, day)
elif length_date == 7 and date.isdigit() and value.count('-') != 2:
# we got a ordinal date: YYYYDDD
date_pattern = "%Y%j"
elif length_date == 8 and date.isdigit():
# we got a calendar date: YYYYMMDD
date_pattern = "%Y%m%d"
else:
raise ValueError("Wrong or incomplete ISO8601:2004 date format")
# check for time zone information
# note that the zone designator is the actual offset from UTC and
# does not include any information on daylight saving time
if time.count('+') == 1 and '+' in time[-6:]:
(time, tz) = time.rsplit('+')
delta = -1
elif time.count('-') == 1 and '-' in time[-6:]:
(time, tz) = time.rsplit('-')
delta = 1
else:
delta = 0
if delta:
while len(tz) < 3:
tz += '0'
delta = delta * (int(tz[0:2]) * 60 * 60 + int(tz[2:]) * 60)
# split microseconds
ms = 0
if '.' in time:
(time, ms) = time.split(".")
ms = float('0.' + ms.strip())
# guess time pattern
length_time = len(time)
if length_time == 6 and time.isdigit():
time_pattern = "%H%M%S"
elif length_time == 4 and time.isdigit():
time_pattern = "%H%M"
elif length_time == 2 and time.isdigit():
time_pattern = "%H"
elif length_time == 0:
time_pattern = ""
else:
raise ValueError("Wrong or incomplete ISO8601:2004 time format")
# parse patterns
dt = datetime.datetime.strptime(date + 'T' + time,
date_pattern + 'T' + time_pattern)
# add microseconds and eventually correct time zone
return UTCDateTime(dt) + (float(delta) + ms)
[docs] def _get_timestamp(self):
"""
Returns UTC timestamp in seconds.
:rtype: float
:return: Timestamp in seconds.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 123456)
>>> dt.timestamp
1222864235.123456
"""
return self.timestamp
[docs] def __float__(self):
"""
Returns UTC timestamp in seconds.
:rtype: float
:return: Timestamp in seconds.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 123456)
>>> float(dt)
1222864235.123456
"""
return self.timestamp
[docs] def _get_datetime(self):
"""
Returns a Python datetime object.
:rtype: :class:`datetime.datetime`
:return: Python datetime object.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.datetime
datetime.datetime(2008, 10, 1, 12, 30, 35, 45020)
"""
# datetime.utcfromtimestamp will cut off but not round
# avoid through adding timedelta - also avoids the year 2038 problem
return TIMESTAMP0 + datetime.timedelta(seconds=self.timestamp)
datetime = property(_get_datetime)
[docs] def _get_date(self):
"""
Returns a Python date object..
:rtype: :class:`datetime.date`
:return: Python date object.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.date
datetime.date(2008, 10, 1)
"""
return self._get_datetime().date()
date = property(_get_date)
[docs] def _get_year(self):
"""
Returns year of the current UTCDateTime object.
:rtype: int
:return: Returns year as an integer.
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11)
>>> dt.year
2012
"""
return self._get_datetime().year
[docs] def _set_year(self, value):
"""
Sets year of current UTCDateTime object.
:param value: Year
:type value: int
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12)
>>> dt.year = 2010
>>> dt
UTCDateTime(2010, 2, 11, 10, 11, 12)
"""
self._set(year=value)
year = property(_get_year, _set_year)
[docs] def _get_month(self):
"""
Returns month as an integer (January is 1, December is 12).
:rtype: int
:return: Returns month as an integer, where January is 1 and December
is 12.
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11)
>>> dt.month
2
"""
return self._get_datetime().month
[docs] def _set_month(self, value):
"""
Sets month of current UTCDateTime object.
:param value: Month
:type value: int
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12)
>>> dt.month = 10
>>> dt
UTCDateTime(2012, 10, 11, 10, 11, 12)
"""
self._set(month=value)
month = property(_get_month, _set_month)
[docs] def _get_day(self):
"""
Returns day as an integer.
:rtype: int
:return: Returns day as an integer.
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11)
>>> dt.day
11
"""
return self._get_datetime().day
[docs] def _set_day(self, value):
"""
Sets day of current UTCDateTime object.
:param value: Day
:type value: int
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12)
>>> dt.day = 20
>>> dt
UTCDateTime(2012, 2, 20, 10, 11, 12)
"""
self._set(day=value)
day = property(_get_day, _set_day)
[docs] def _get_weekday(self):
"""
Return the day of the week as an integer (Monday is 0, Sunday is 6).
:rtype: int
:return: Returns day of the week as an integer, where Monday is 0 and
Sunday is 6.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.weekday
2
"""
return self._get_datetime().weekday()
weekday = property(_get_weekday)
[docs] def _get_time(self):
"""
Returns a Python time object.
:rtype: :class:`datetime.time`
:return: Python time object.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.time
datetime.time(12, 30, 35, 45020)
"""
return self._get_datetime().time()
time = property(_get_time)
[docs] def _get_hour(self):
"""
Returns hour as an integer.
:rtype: int
:return: Returns hour as an integer.
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12)
>>> dt.hour
10
"""
return self._get_datetime().hour
[docs] def _set_hour(self, value):
"""
Sets hours of current UTCDateTime object.
:param value: Hours
:type value: int
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12)
>>> dt.hour = 20
>>> dt
UTCDateTime(2012, 2, 11, 20, 11, 12)
"""
self._set(hour=value)
hour = property(_get_hour, _set_hour)
[docs] def _get_minute(self):
"""
Returns minute as an integer.
:rtype: int
:return: Returns minute as an integer.
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12)
>>> dt.minute
11
"""
return self._get_datetime().minute
[docs] def _set_minute(self, value):
"""
Sets minutes of current UTCDateTime object.
:param value: Minutes
:type value: int
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12)
>>> dt.minute = 20
>>> dt
UTCDateTime(2012, 2, 11, 10, 20, 12)
"""
self._set(minute=value)
minute = property(_get_minute, _set_minute)
[docs] def _get_second(self):
"""
Returns seconds as an integer.
:rtype: int
:return: Returns seconds as an integer.
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12)
>>> dt.second
12
"""
return self._get_datetime().second
[docs] def _set_second(self, value):
"""
Sets seconds of current UTCDateTime object.
:param value: Seconds
:type value: int
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12)
>>> dt.second = 20
>>> dt
UTCDateTime(2012, 2, 11, 10, 11, 20)
"""
self.timestamp += value - self.second
second = property(_get_second, _set_second)
[docs] def _get_microsecond(self):
"""
Returns microseconds as an integer.
:rtype: int
:return: Returns microseconds as an integer.
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12, 345234)
>>> dt.microsecond
345234
"""
return self._get_datetime().microsecond
[docs] def _set_microsecond(self, value):
"""
Sets microseconds of current UTCDateTime object.
:param value: Microseconds
:type value: int
.. rubric:: Example
>>> dt = UTCDateTime(2012, 2, 11, 10, 11, 12, 345234)
>>> dt.microsecond = 999123
>>> dt
UTCDateTime(2012, 2, 11, 10, 11, 12, 999123)
"""
self._set(microsecond=value)
microsecond = property(_get_microsecond, _set_microsecond)
[docs] def _get_julday(self):
"""
Returns Julian day as an integer.
:rtype: int
:return: Julian day as an integer.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.julday
275
"""
return self.utctimetuple().tm_yday
[docs] def _set_julday(self, value):
"""
Sets Julian day of current UTCDateTime object.
:param value: Julian day
:type value: int
.. rubric:: Example
>>> dt = UTCDateTime(2008, 12, 5, 12, 30, 35, 45020)
>>> dt.julday = 275
>>> dt
UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
"""
self._set(julday=value)
julday = property(_get_julday, _set_julday)
[docs] def timetuple(self):
"""
Return a time.struct_time such as returned by time.localtime().
:rtype: time.struct_time
"""
return self._get_datetime().timetuple()
[docs] def utctimetuple(self):
"""
Return a time.struct_time of current UTCDateTime object.
:rtype: time.struct_time
"""
return self._get_datetime().utctimetuple()
[docs] def __add__(self, value):
"""
Adds seconds and microseconds to current UTCDateTime object.
:type value: int, float
:param value: Seconds to add
:rtype: :class:`~obspy.core.utcdatetime.UTCDateTime`
:return: New UTCDateTime object.
.. rubric:: Example
>>> dt = UTCDateTime(1970, 1, 1, 0, 0)
>>> dt + 2
UTCDateTime(1970, 1, 1, 0, 0, 2)
>>> UTCDateTime(1970, 1, 1, 0, 0) + 1.123456
UTCDateTime(1970, 1, 1, 0, 0, 1, 123456)
"""
if isinstance(value, datetime.timedelta):
# see datetime.timedelta.total_seconds
value = (value.microseconds + (value.seconds + value.days *
86400) * 1000000) / 1000000.0
return UTCDateTime(self.timestamp + value)
[docs] def __sub__(self, value):
"""
Subtracts seconds and microseconds from current UTCDateTime object.
:type value: int, float or :class:`~obspy.core.utcdatetime.UTCDateTime`
:param value: Seconds or UTCDateTime object to subtract. Subtracting an
UTCDateTime objects results into a relative time span in seconds.
:rtype: :class:`~obspy.core.utcdatetime.UTCDateTime` or float
:return: New UTCDateTime object or relative time span in seconds.
.. rubric:: Example
>>> dt = UTCDateTime(1970, 1, 2, 0, 0)
>>> dt - 2
UTCDateTime(1970, 1, 1, 23, 59, 58)
>>> UTCDateTime(1970, 1, 2, 0, 0) - 1.123456
UTCDateTime(1970, 1, 1, 23, 59, 58, 876544)
>>> UTCDateTime(1970, 1, 2, 0, 0) - UTCDateTime(1970, 1, 1, 0, 0)
86400.0
"""
if isinstance(value, UTCDateTime):
return round(self.timestamp - value.timestamp, self.__precision)
elif isinstance(value, datetime.timedelta):
# see datetime.timedelta.total_seconds
value = (value.microseconds + (value.seconds + value.days *
86400) * 1000000) / 1000000.0
return UTCDateTime(self.timestamp - value)
[docs] def __str__(self):
"""
Returns ISO8601 string representation from current UTCDateTime object.
:return: string
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> str(dt)
'2008-10-01T12:30:35.045020Z'
"""
return "%s%sZ" % (self.strftime('%Y-%m-%dT%H:%M:%S'),
(self.__ms_pattern % (abs(self.timestamp % 1)))[1:])
[docs] def _repr_pretty_(self, p, cycle):
p.text(str(self))
[docs] def __unicode__(self):
"""
Returns ISO8601 unicode representation from current UTCDateTime object.
:return: string
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.__unicode__()
'2008-10-01T12:30:35.045020Z'
"""
return str(self.__str__())
[docs] def __eq__(self, other):
"""
Rich comparison operator '=='.
.. rubric: Example
Comparing two UTCDateTime object will always compare timestamps rounded
to a precision of 6 digits by default.
>>> t1 = UTCDateTime(123.000000012)
>>> t2 = UTCDateTime(123.000000099)
>>> t1 == t2
True
But the actual timestamp differ
>>> t1.timestamp == t2.timestamp
False
Resetting the precision changes the behavior of the operator
>>> t1.precision = 11
>>> t1 == t2
False
"""
try:
return round(self.timestamp - float(other), self.__precision) == 0
except (TypeError, ValueError):
return False
[docs] def __ne__(self, other):
"""
Rich comparison operator '!='.
.. rubric: Example
Comparing two UTCDateTime object will always compare timestamps rounded
to a precision of 6 digits by default.
>>> t1 = UTCDateTime(123.000000012)
>>> t2 = UTCDateTime(123.000000099)
>>> t1 != t2
False
But the actual timestamp differ
>>> t1.timestamp != t2.timestamp
True
Resetting the precision changes the behavior of the operator
>>> t1.precision = 11
>>> t1 != t2
True
"""
return not self.__eq__(other)
[docs] def __lt__(self, other):
"""
Rich comparison operator '<'.
.. rubric: Example
Comparing two UTCDateTime object will always compare timestamps rounded
to a precision of 6 digits by default.
>>> t1 = UTCDateTime(123.000000012)
>>> t2 = UTCDateTime(123.000000099)
>>> t1 < t2
False
But the actual timestamp differ
>>> t1.timestamp < t2.timestamp
True
Resetting the precision changes the behavior of the operator
>>> t1.precision = 11
>>> t1 < t2
True
"""
try:
return round(self.timestamp - float(other), self.__precision) < 0
except (TypeError, ValueError):
return False
[docs] def __le__(self, other):
"""
Rich comparison operator '<='.
.. rubric: Example
Comparing two UTCDateTime object will always compare timestamps rounded
to a precision of 6 digits by default.
>>> t1 = UTCDateTime(123.000000099)
>>> t2 = UTCDateTime(123.000000012)
>>> t1 <= t2
True
But the actual timestamp differ
>>> t1.timestamp <= t2.timestamp
False
Resetting the precision changes the behavior of the operator
>>> t1.precision = 11
>>> t1 <= t2
False
"""
try:
return round(self.timestamp - float(other), self.__precision) <= 0
except (TypeError, ValueError):
return False
[docs] def __gt__(self, other):
"""
Rich comparison operator '>'.
.. rubric: Example
Comparing two UTCDateTime object will always compare timestamps rounded
to a precision of 6 digits by default.
>>> t1 = UTCDateTime(123.000000099)
>>> t2 = UTCDateTime(123.000000012)
>>> t1 > t2
False
But the actual timestamp differ
>>> t1.timestamp > t2.timestamp
True
Resetting the precision changes the behavior of the operator
>>> t1.precision = 11
>>> t1 > t2
True
"""
try:
return round(self.timestamp - float(other), self.__precision) > 0
except (TypeError, ValueError):
return False
[docs] def __ge__(self, other):
"""
Rich comparison operator '>='.
.. rubric: Example
Comparing two UTCDateTime object will always compare timestamps rounded
to a precision of 6 digits by default.
>>> t1 = UTCDateTime(123.000000012)
>>> t2 = UTCDateTime(123.000000099)
>>> t1 >= t2
True
But the actual timestamp differ
>>> t1.timestamp >= t2.timestamp
False
Resetting the precision changes the behavior of the operator
>>> t1.precision = 11
>>> t1 >= t2
False
"""
try:
return round(self.timestamp - float(other), self.__precision) >= 0
except (TypeError, ValueError):
return False
[docs] def __repr__(self):
"""
Returns a representation of UTCDatetime object.
"""
return 'UTCDateTime' + self._get_datetime().__repr__()[17:]
[docs] def __abs__(self):
"""
Returns absolute timestamp value of the current UTCDateTime object.
"""
# needed for unittest.assertAlmostEqual tests on Linux
return abs(self.timestamp)
[docs] def __hash__(self):
"""
An object is hashable if it has a hash value which never changes
during its lifetime. As an UTCDateTime object may change over time,
it's not hashable. Use the :meth:`~UTCDateTime.datetime()` method to
generate a :class:`datetime.datetime` object for hashing. But be aware:
once the UTCDateTime object changes, the hash is not valid anymore.
"""
# explicitly flag it as unhashable
return None
[docs] def strftime(self, format):
"""
Return a string representing the date and time, controlled by an
explicit format string.
:type format: str
:param format: Format string.
:return: Formatted string representing the date and time.
Format codes referring to hours, minutes or seconds will see 0 values.
See methods :meth:`~datetime.datetime.strftime()` and
:meth:`~datetime.datetime.strptime()` for more information.
"""
return self._get_datetime().strftime(format)
[docs] def strptime(self, date_string, format):
"""
Return a UTCDateTime corresponding to date_string, parsed according to
given format.
:type date_string: str
:param date_string: Date and time string.
:type format: str
:param format: Format string.
:return: :class:`~obspy.core.utcdatetime.UTCDateTime`
See methods :meth:`~datetime.datetime.strftime()` and
:meth:`~datetime.datetime.strptime()` for more information.
"""
return UTCDateTime(datetime.datetime.strptime(date_string, format))
[docs] def timetz(self):
"""
Return time object with same hour, minute, second, microsecond, and
tzinfo attributes. See also method :meth:`datetime.datetime.time()`.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.timetz()
datetime.time(12, 30, 35, 45020)
"""
return self._get_datetime().timetz()
[docs] def utcoffset(self):
"""
Returns None (to stay compatible with :class:`datetime.datetime`)
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.utcoffset()
"""
return self._get_datetime().utcoffset()
[docs] def dst(self):
"""
Returns None (to stay compatible with :class:`datetime.datetime`)
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.dst()
"""
return self._get_datetime().dst()
[docs] def tzname(self):
"""
Returns None (to stay compatible with :class:`datetime.datetime`)
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.tzname()
"""
return self._get_datetime().tzname()
[docs] def ctime(self):
"""
Return a string representing the date and time.
.. rubric:: Example
>>> UTCDateTime(2002, 12, 4, 20, 30, 40).ctime()
'Wed Dec 4 20:30:40 2002'
"""
return self._get_datetime().ctime()
[docs] def isoweekday(self):
"""
Return the day of the week as an integer (Monday is 1, Sunday is 7).
:rtype: int
:return: Returns day of the week as an integer, where Monday is 1 and
Sunday is 7.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.isoweekday()
3
"""
return self._get_datetime().isoweekday()
[docs] def isocalendar(self):
"""
Returns a tuple containing (ISO year, ISO week number, ISO weekday).
:rtype: tuple of ints
:return: Returns a tuple containing ISO year, ISO week number and ISO
weekday.
.. rubric:: Example
>>> dt = UTCDateTime(2008, 10, 1, 12, 30, 35, 45020)
>>> dt.isocalendar()
(2008, 40, 3)
"""
return self._get_datetime().isocalendar()
@deprecated(
"'formatFissures' has been renamed to " # noqa
"'format_fissures'. Use that instead.")
@deprecated(
"'formatArcLink' has been renamed to " # noqa
"'format_arclink'. Use that instead.")
@deprecated(
"'formatSeedLink' has been renamed to " # noqa
"'format_seedlink'. Use that instead.")
@deprecated(
"'formatSEED' has been renamed to " # noqa
"'format_seed'. Use that instead.")
@deprecated(
"'formatIRISWebService' has been renamed to " # noqa
"'format_iris_web_service'. Use that instead.")
[docs] def _get_precision(self):
"""
Returns precision of current UTCDateTime object.
:return: int
.. rubric:: Example
>>> dt = UTCDateTime()
>>> dt.precision
6
"""
return self.__precision
[docs] def _set_precision(self, value=6):
"""
Set precision of current UTCDateTime object.
:type value: int, optional
:param value: Precision value used by the rich comparison operators.
Defaults to ``6``.
.. rubric:: Example
(1) Default precision
>>> dt = UTCDateTime()
>>> dt.precision
6
(2) Set precision during initialization of UTCDateTime object.
>>> dt = UTCDateTime(precision=5)
>>> dt.precision
5
(3) Set precision for an existing UTCDateTime object.
>>> dt = UTCDateTime()
>>> dt.precision = 12
>>> dt.precision
12
"""
self.__precision = int(value)
self.__ms_pattern = "%%0.%df" % (self.__precision)
precision = property(_get_precision, _set_precision)
[docs] def toordinal(self):
"""
Return proleptic Gregorian ordinal. January 1 of year 1 is day 1.
See :meth:`datetime.datetime.toordinal()`.
:return: int
.. rubric:: Example
>>> dt = UTCDateTime(2012, 1, 1)
>>> dt.toordinal()
734503
"""
return self._get_datetime().toordinal()
@staticmethod
[docs] def now():
"""
Returns current UTC datetime.
"""
return UTCDateTime()
@staticmethod
[docs] def utcnow():
"""
Returns current UTC datetime.
"""
return UTCDateTime()
[docs] def _get_hours_after_midnight(self):
"""
Calculate foating point hours after midnight.
>>> t = UTCDateTime("2015-09-27T03:16:12.123456Z")
>>> t._get_hours_after_midnight()
3.270034293333333
"""
timedelta = (
self.datetime -
self.datetime.replace(hour=0, minute=0, second=0, microsecond=0))
return timedelta.total_seconds() / 3600.0
if __name__ == '__main__':
import doctest
doctest.testmod(exclude_empty=True)