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