mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
timeUtils.cpp
Go to the documentation of this file.
1 /** \file timeUtils.cpp
2  * \brief Definitions for utilities for working with time
3  *
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  * \ingroup utils_files
7  *
8  */
9 
10 //***********************************************************************//
11 // Copyright 2020 Jared R. Males (jaredmales@gmail.com)
12 //
13 // This file is part of mxlib.
14 //
15 // mxlib is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 // mxlib is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU General Public License for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
27 //***********************************************************************//
28 
29 #include "sys/timeUtils.hpp"
30 
31 namespace mx
32 {
33 namespace sys
34 {
35 
36 template<>
37 double get_curr_time<double, CLOCK_REALTIME>(timespec & tsp)
38 {
39  clock_gettime(CLOCK_REALTIME, &tsp);
40 
41  return ((double)tsp.tv_sec) + ((double)tsp.tv_nsec)/1e9;
42 }
43 
44 template<>
45 double get_curr_time<double, CLOCK_REALTIME>()
46 {
47  struct timespec tsp;
48  return get_curr_time<double,CLOCK_REALTIME>(tsp);
49 }
50 
51 void sleep( unsigned sec )
52 {
53  std::this_thread::sleep_for(std::chrono::seconds(sec));
54 }
55 
56 void milliSleep( unsigned msec )
57 {
58  std::this_thread::sleep_for(std::chrono::milliseconds(msec));
59 }
60 
61 void microSleep( unsigned usec )
62 {
63  std::this_thread::sleep_for(std::chrono::microseconds(usec));
64 }
65 
66 void nanoSleep( unsigned nsec )
67 {
68  std::this_thread::sleep_for(std::chrono::nanoseconds(nsec));
69 }
70 
71 void timespecAddNsec( timespec & ts,
72  unsigned nsec
73  )
74 {
75  ts.tv_nsec += nsec % 1000000000;
76  ts.tv_sec += nsec / 1000000000;
77 
78  if(ts.tv_nsec > 999999999)
79  {
80  ts.tv_nsec -= 1000000000;
81  ts.tv_sec += 1;
82  }
83 }
84 
85 double Cal2mjd( int yr,
86  int mon,
87  int day,
88  int hr,
89  int min,
90  double sec
91  )
92 {
93  double djm0;
94  double djm;
95 
96  int rv = sofa::iauCal2jd(yr, mon, day, &djm0, &djm);
97 
98  if (rv < 0) return (double) rv;
99 
100 
101  djm0 = djm + (( (double) hr)/ (24.0) + ( (double) min)/ (60.0*24.0) + sec / (3600.0*24.0));
102 
103  return djm0;
104 }
105 
106 int ISO8601dateBreakdown( int & yr,
107  int & mon,
108  int & day,
109  int & hr,
110  int & min,
111  double & sec,
112  const std::string & fdate
113  )
114 {
115  if(fdate.length() < 19) return -4;
116 
117 
118  yr = atoi(fdate.substr(0,4).c_str());
119  mon = atoi(fdate.substr(5,2).c_str());
120  day = atoi(fdate.substr(8,2).c_str());
121 
122  double _hr, _min;
123  parse_hms( _hr, _min, sec, fdate.substr(11));
124 
125  hr = floor(_hr);
126  min = floor(_min);
127 
128  return 0;
129 
130 }
131 
132 double ISO8601date2mjd(const std::string & fdate)
133 {
134  if(fdate.length() < 19) return -4;
135 
136  int yr, mon, day, hr, min;
137  //double hr, min, sec;
138  double sec;
139 
140  ISO8601dateBreakdown( yr, mon, day, hr, min, sec, fdate);
141 
142  return Cal2mjd(yr,mon,day, hr, min, sec);
143 
144 }
145 
146 template<>
147 std::string ISO8601DateTimeStr<time_t>( const time_t &timeIn,
148  int timeZone
149  )
150 {
151  tm bdt;
152  gmtime_r(&timeIn, &bdt);
153 
154  char tstr[25];
155 
156  strftime(tstr, 25, "%FT%H:%M:%S", &bdt);
157 
158  std::string result = tstr;
159 
160  if(timeZone == 1) result += "Z";
161  if(timeZone == 2) result += "+00:00";
162 
163  return result;
164 }
165 
166 template<>
167 std::string ISO8601DateTimeStr<timespec>( const timespec &timeIn,
168  int timeZone
169  )
170 {
171  std::string result = ISO8601DateTimeStr<time_t>(timeIn.tv_sec, 0);
172 
173  char tstr[20];
174 
175  snprintf(tstr, 20, ".%09ld", timeIn.tv_nsec);
176 
177  result += tstr;
178 
179  if(timeZone == 1) result += "Z";
180  if(timeZone == 2) result += "+00:00";
181 
182  return result;
183 }
184 
185 std::string ISO8601DateTimeStr(int timeZone)
186 {
187  return ISO8601DateTimeStr<time_t>(::time(0), timeZone);
188 }
189 
190 std::string ISO8601DateTimeStrMJD( const double &timeIn,
191  int timeZone
192  )
193 {
194  int iy, im, id;
195  double fd;
196 
197  sofa::iauJd2cal( DJM0, timeIn, &iy, &im, &id, &fd);
198 
199  int hr, mn;
200 
201  hr = floor(fd*24.0);
202  fd = (fd - hr/24.0)*24.0;
203 
204  mn = floor(fd*60.);
205 
206  fd = (fd - mn/60.0)*3600.0;
207 
208  char tstr[32];
209 
210  snprintf(tstr, 32, "%04d-%02d-%02dT%02d:%02d:%012.9f", iy,im,id,hr,mn,fd);
211 
212  std::string result = tstr;
213 
214  if(timeZone == 1) result += "Z";
215  if(timeZone == 2) result += "+00:00";
216 
217  return result;
218 }
219 
220 int timeStamp( std::string & tstamp,
221  timespec & ts
222  )
223 {
224  tm uttime;//The broken down time.
225 
226  time_t t0 = ts.tv_sec;
227 
228  if(gmtime_r(&t0, &uttime) == 0)
229  {
230  std::cerr << "Error getting UT time (gmtime_r returned 0). At: " << __FILE__ << " " << __LINE__ << "\n";
231  return -1;
232  }
233 
234  char buffer[48];
235 
236  snprintf(buffer, sizeof(buffer), "%04i%02i%02i%02i%02i%02i%09i", uttime.tm_year+1900, uttime.tm_mon+1, uttime.tm_mday, uttime.tm_hour, uttime.tm_min, uttime.tm_sec, static_cast<int>(ts.tv_nsec)); //casting in case we switch type of time_ns.
237 
238  tstamp = buffer;
239 
240  return 0;
241 }
242 
243 int timespecUTC2TAIMJD( double & djm,
244  double & djmf,
245  const timespec & tsp,
246  tm * tm0
247  )
248 {
249  double dat, djm0;
250  tm *tmrv;
251  int rv1, rv2;
252 
253  // Get the broken down time corresponding to tsp0
254  tmrv = gmtime_r(&tsp.tv_sec, tm0);
255  if(tmrv == 0) return -10;
256 
257  // Then determine deltaAT = TAI-UTC
258  rv1 = sofa::iauDat(1900+tm0->tm_year, 1+tm0->tm_mon, tm0->tm_mday, 0.0, &dat);
259  if(rv1 < 0) return rv1;
260 
261  // And get the MJD
262  rv2 = sofa::iauCal2jd(1900+tm0->tm_year, 1+tm0->tm_mon, tm0->tm_mday, &djm0, &djm);
263  if(rv2 < 0) return rv2;
264 
265  // Finally calculate the day fraction
266  djmf = ((double) tm0->tm_hour)/24.0 + ((double) tm0->tm_min)/(24.0*60.) + (((double) tm0->tm_sec)+((double) tsp.tv_nsec/1e9) + dat )/(24.0*3600.0);
267 
268  if(djmf >= 1.0)
269  {
270  djmf -= 1.0;
271  djm += 1.0;
272  }
273 
274  if(rv1) return rv1;
275  return 0;
276 }
277 
278 timespec meanTimespec( timespec ts1,
279  timespec ts2
280  )
281 {
282  double means = (ts1.tv_sec + ts2.tv_sec)/2.0;
283  double meanns = (ts1.tv_nsec + ts2.tv_nsec)/2.0;
284 
285  ts1.tv_sec = floor(means);
286  ts1.tv_nsec = round(meanns);
287 
288  if( means != floor(means) )
289  {
290  ts1.tv_nsec += 5e8;
291 
292  if(ts1.tv_nsec >= 1e9)
293  {
294  ts1.tv_sec += 1;
295  ts1.tv_nsec -= 1e9;
296  }
297  }
298 
299  return ts1;
300 }
301 
302 
303 namespace tscomp
304 {
305 
306 bool operator<( timespec const& tsL,
307  timespec const& tsR
308  )
309 {
310  return ( ((tsL.tv_sec == tsR.tv_sec) && (tsL.tv_nsec < tsR.tv_nsec)) || (tsL.tv_sec < tsR.tv_sec));
311 }
312 
313 bool operator>( timespec const& tsL,
314  timespec const& tsR
315  )
316 {
317  return ( ((tsL.tv_sec == tsR.tv_sec) && (tsL.tv_nsec > tsR.tv_nsec)) || (tsL.tv_sec > tsR.tv_sec));
318 }
319 
320 bool operator==( timespec const& tsL,
321  timespec const& tsR
322  )
323 {
324  return ( (tsL.tv_sec == tsR.tv_sec) && (tsL.tv_nsec == tsR.tv_nsec) );
325 }
326 
327 bool operator<=( timespec const& tsL,
328  timespec const& tsR
329  )
330 {
331  return ( tsL < tsR || tsL == tsR );
332 }
333 
334 bool operator>=( timespec const& tsL,
335  timespec const& tsR
336  )
337 {
338  return ( tsL > tsR || tsL == tsR );
339 }
340 
341 } //namespace tscomp
342 
343 
344 } //namespace sys
345 } //namespace mx
constexpr units::realT day()
Length of day.
Definition: constants.hpp:100
void nanoSleep(unsigned nsec)
Sleep for a specified period in nanoseconds.
Definition: timeUtils.cpp:66
void sleep(unsigned sec)
Sleep for a specified period in seconds.
Definition: timeUtils.cpp:51
void milliSleep(unsigned msec)
Sleep for a specified period in milliseconds.
Definition: timeUtils.cpp:56
void microSleep(unsigned usec)
Sleep for a specified period in microseconds.
Definition: timeUtils.cpp:61
bool operator<(timespec const &tsL, timespec const &tsR)
Timespec comparison operator < (see caveats)
Definition: timeUtils.cpp:306
bool operator>(timespec const &tsL, timespec const &tsR)
Timespec comparison operator > (see caveats)
Definition: timeUtils.cpp:313
bool operator>=(timespec const &tsL, timespec const &tsR)
Timespec comparison operator >= (see caveats)
Definition: timeUtils.cpp:334
bool operator<=(timespec const &tsL, timespec const &tsR)
Timespec comparison operator <= (see caveats)
Definition: timeUtils.cpp:327
int ISO8601dateBreakdown(int &yr, int &mon, int &day, int &hr, int &min, double &sec, const std::string &fdate)
Parse an ISO8601 date of the form "YYYY-MM-DDTHH:MM:SS.S" into the individual components.
Definition: timeUtils.cpp:106
std::string ISO8601DateTimeStr(const timeT &timeIn, int timeZone=0)
Get a date-time string in ISO 8601 format.
std::string ISO8601DateTimeStrMJD(const double &timeIn, int timeZone=0)
Get a date-time string in ISO 8601 format for an MJD.
Definition: timeUtils.cpp:190
int timespecUTC2TAIMJD(double &djm, double &djmf, const timespec &tsp, tm *tm0)
Convert a UTC timespec to TAI modified Julian date.
Definition: timeUtils.cpp:243
std::string ISO8601DateTimeStr< timespec >(const timespec &timeIn, int timeZone)
Get a date-time string in ISO 8601 format for timespec.
Definition: timeUtils.cpp:167
void timespecAddNsec(timespec &ts, unsigned nsec)
Adds a time offset to an existing timespec.
Definition: timeUtils.cpp:71
void parse_hms(floatT &h, floatT &m, floatT &s, const std::string &hmsstr)
Definition: timeUtils.hpp:155
int timeStamp(std::string &tstamp, timespec &ts)
Get a timestamp string in the form YYYYMMDDHHMMSS.SSSSSSSSS.
Definition: timeUtils.cpp:220
double Cal2mjd(int yr, int mon, int day, int hr, int min, double sec)
Converts a Gregorian calendar date into modified Julian date (MJD).
Definition: timeUtils.cpp:85
double ISO8601date2mjd(const std::string &fdate)
Parse an ISO8601 date of the form "YYYY-MM-DDTHH:MM:SS.S" and return the modified Julian date (MJD)
Definition: timeUtils.cpp:132
std::string ISO8601DateTimeStr< time_t >(const time_t &timeIn, int timeZone)
Get a date-time string in ISO 8601 format for time_t.
Definition: timeUtils.cpp:147
The mxlib c++ namespace.
Definition: mxError.hpp:107
Utilities for working with time.
timespec meanTimespec(timespec ts1, timespec ts2)
Calculate the mean time of two times given by timespecs.
Definition: timeUtils.cpp:278