-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathaccuratetime.py
177 lines (155 loc) · 5.58 KB
/
accuratetime.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# coding=utf-8
#
#
# Copyright (C) 2012 Marco Bartolini, marco.bartolini@gmail.com
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
ACCURATE TIME
=============
This module defines an AccurateTime object for storing arbitrary precision
floating point posix time while keeping the same information as a standard
datetime object, keeping consistency between the two
INSTALLATION
============
You are free to clone the public git repo as::
$ git clone git://github.com/flyingfrog81/accuratetime.git
$ cd accuratetime
$ python setup.py install
Or you can install using PyPI as::
$ pip install accuratetime
USAGE
=====
>>> import accuratetime
>>> import time
>>> t_zero = accuratetime.now()
>>> time.sleep(3.5)
>>> t_uno = accuratetime.now()
>>> t_delta_datetime = t_uno.datetime - t_zero.datetime
>>> t_zero.datetime += t_delta_datetime
>>> t_zero.accurate_posix == t_uno.accurate_posix
True
>>> t_uno = accuratetime.now()
>>> t_delta_posix = t_uno.accurate_posix - t_zero.accurate_posix
>>> t_zero.accurate_posix += t_delta_posix
>>> t_zero.datetime == t_uno.datetime
True
@author: Marco Bartolini
@contact: marco.bartolini@gmail.com
@version: 0.5
"""
import datetime
import time
#from functools import total_ordering #Python2.7
#@total_ordering
class AccurateTime(object):
'''
Class for storing a POSIX time with arbitrary floating point precision.
It can return datetime objects as well as posix time and the values are
kept synchronized between each other.
In order to keep consisency between datetime object and posix time
information, changes must be made using I{datetime} and I{accurate_posix}
public attributes.
'''
def __init__(self, ptime=0):
"""
Constructor. Module function can be used for type conversion.
@type ptime: float
@param ptime: seconds since Epoch
"""
self._datetime = datetime.datetime.fromtimestamp(ptime)
self._accurate_posix = float(ptime)
@property
def accurate_posix(self):
"""
The posix time representation of the information. Stored in arbitrary
precision.
"""
return self._accurate_posix
@accurate_posix.setter
def accurate_posix(self, new_val):
self._accurate_posix = new_val
self._datetime = datetime.datetime.fromtimestamp(new_val)
@property
def datetime(self):
"""
The datetime representation of the information. You can modify this
attribute using datetime python utilities and relative changes will be reflected
in the accurate_posix attribute.
"""
return self._datetime
@datetime.setter
def datetime(self, new_val):
td = new_val - self._datetime
self._datetime = new_val
self._accurate_posix += td.total_seconds()
def microseconds(self):
"""
Gives the exact microsecond of the represented time
@return: a floating point number representing microseconds
"""
return self._accurate_posix % 1 * 1000000
def __add__(self, other):
"""
Addition operator.
@type other: a datetime.timedelta instance or a numeric type
@param other: a time difference
@return: a new L{AccurateTime} instance
@raise TypeError: if values cannot be summed up
"""
try:
return from_datetime(self._datetime + other)
except TypeError:
try:
return from_ptime(self._accurate_posix + other)
except TypeError:
raise TypeError("unsupported operand type(s) for +: 'AccurateTime' and " + type(other))
def __sub__(self, other):
"""
Subtraction operator.
@type other: a datetime.timedelta instance or a numeric type
@param other: a time difference
@return: a new L{AccurateTime} instance
@raise TypeError: if values cannot be subtracted from each other
"""
try:
return from_datetime(self._datetime - other)
except TypeError:
try:
return from_ptime(self._accurate_posix - other)
except TypeError:
raise TypeError("unsupported operand type(s) for +: 'AccurateTime' and '" + str(type(other)) + "'")
def from_datetime(dt):
"""
Creates a new AccurateTime object with given informations
@type dt: datetime.datetime
@param dt: the datetime object to be parsed
@return: the AccurateTime instance
"""
return AccurateTime(time.mktime(dt.timetuple()))
def from_ptime(pt):
"""
Creates a new AccurateTime object with given informations
@type pt: float
@param pt: posix time as a floating point number
@return: the AccurateTime instance
"""
return AccurateTime(pt)
def now():
"""
Creates a new AccurateTime object representing the I{now} time
@return: the AccurateTime instance
"""
return AccurateTime(time.mktime(datetime.datetime.now().timetuple()))