f7fbc853735b7743e70cda222018da6a7f6a6ad6
[nepi.git] / src / nepi / util / timefuncs.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
5 #    This program is free software: you can redistribute it and/or modify
6 #    it under the terms of the GNU General Public License as published by
7 #    the Free Software Foundation, either version 3 of the License, or
8 #    (at your option) any later version.
9 #
10 #    This program is distributed in the hope that it will be useful,
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #    GNU General Public License for more details.
14 #
15 #    You should have received a copy of the GNU General Public License
16 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19
20
21 import datetime
22 import re
23
24 _strf = "%Y%m%d%H%M%S%f"
25 _reabs = re.compile("^\d{20}$")
26 _rerel = re.compile("^(?P<time>\d+(.\d+)?)(?P<units>h|m|s|ms|us)$")
27
28 # Work around to fix "ImportError: Failed to import _strptime because the import lock is held by another thread."
29 datetime.datetime.strptime("20120807124732894211", _strf)
30
31 def stformat(sdate):
32     """ Constructs a datetime object from a string date with
33     format YYYYMMddHHMMSSffff 
34
35     """
36     return datetime.datetime.strptime(sdate, _strf).date()
37
38 def tsformat(date = None):
39     """ Formats a datetime object to a string with format YYYYMMddHHMMSSffff.
40     If no date is given, the current date is used.
41     
42     """
43     if not date:
44         date = tnow()
45
46     return date.strftime(_strf)
47
48 def tnow():
49     """ Returns datetime object with the current time """
50     return datetime.datetime.now()
51
52 def tdiff(date1, date2):
53     """ Returns difference ( date1 - date2 ) as a datetime object,
54     where date1 and date 2 are datetime objects 
55     
56     """
57     return date1 - date2
58
59 def _get_total_seconds(td): 
60     return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 1e6) / 1e6
61
62 def tdiffsec(date1, date2):
63     """ Returns the date difference ( date1 - date2 ) in seconds,
64     where date1 and date 2 are datetime objects 
65     
66     """
67     diff = tdiff(date1, date2)
68     return _get_total_seconds(diff)
69
70 def stabsformat(sdate, dbase = None):
71     """ Constructs a datetime object from a string date.
72     The string date can be expressed as an absolute date
73     ( i.e. format YYYYMMddHHMMSSffff ) or as a relative time
74     ( e.g. format '5m' or '10s'). 
75     If the date is a relative time and the dbase parameter 
76     is given (dbase must be datetime object), the returned
77     date will be dbase + sdate. If dbase is None, 
78     current time will be used instead as base time.
79
80     :param date : string date  
81     :type date : date 
82
83     """
84
85     # No date given, return current datetime
86     if not sdate:
87         return tnow()
88
89     # Absolute date is given
90     if _reabs.match(sdate):
91         return stformat(sdate)
92
93     # Relative time is given
94     m = _rerel.match(sdate)
95     if m:
96         time = float(m.groupdict()['time'])
97         units = m.groupdict()['units']
98         if units == 'h':
99             delta = datetime.timedelta(hours = time) 
100         elif units == 'm':
101             delta = datetime.timedelta(minutes = time) 
102         elif units == 's':
103             delta = datetime.timedelta(seconds = time) 
104         elif units == 'ms':
105             delta = datetime.timedelta(microseconds = (time*1000)) 
106         else:
107             delta = datetime.timedelta(microseconds = time)
108         
109         if not dbase:
110             dbase = tnow()
111
112         return dbase + delta
113
114     return None
115
116 def compute_delay_ms(timestamp2, timestamp1):
117     d1 = datetime.datetime.fromtimestamp(float(timestamp1))
118     d2 = datetime.datetime.fromtimestamp(float(timestamp2))
119     delay = d2 - d1
120
121     # round up resolution - round up to miliseconds
122     return delay.total_seconds() * 1000
123