222 ts.tv_nsec = (long int)((total_sec - ts.tv_sec)*1e9); |
221 ts.tv_nsec = (long int)((total_sec - ts.tv_sec)*1e9); |
223 |
222 |
224 return ts; |
223 return ts; |
225 } |
224 } |
226 |
225 |
227 #ifdef __MINGW32__ |
226 #define EPOCH_YEAR 1970 |
228 #define TIMEGM mktime |
227 #define SECONDS_PER_HOUR (60 * 60) |
229 #else |
228 #define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) |
230 #define TIMEGM timegm |
229 #define __isleap(year) \ |
231 #endif |
230 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) |
|
231 static const unsigned short int __mon_yday[2][13] = |
|
232 { |
|
233 /* Normal years. */ |
|
234 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, |
|
235 /* Leap years. */ |
|
236 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} |
|
237 }; |
|
238 |
|
239 typedef struct { |
|
240 int tm_sec; /* Seconds. [0-60] (1 leap second) */ |
|
241 int tm_min; /* Minutes. [0-59] */ |
|
242 int tm_hour; /* Hours. [0-23] */ |
|
243 int tm_day; /* Day. [1-31] */ |
|
244 int tm_mon; /* Month. [0-11] */ |
|
245 int tm_year; /* Year */ |
|
246 } tm; |
|
247 |
|
248 static inline tm convert_seconds_to_date_and_time(long int seconds) { |
|
249 tm dt; |
|
250 long int days, rem; |
|
251 days = seconds / SECONDS_PER_DAY; |
|
252 rem = seconds % SECONDS_PER_DAY; |
|
253 if (rem < 0) { |
|
254 rem += SECONDS_PER_DAY; |
|
255 days--; |
|
256 } |
|
257 |
|
258 // time of day |
|
259 dt.tm_hour = rem / SECONDS_PER_HOUR; |
|
260 rem %= SECONDS_PER_HOUR; |
|
261 dt.tm_min = rem / 60; |
|
262 dt.tm_sec = rem % 60; |
|
263 |
|
264 // date |
|
265 dt.tm_year = EPOCH_YEAR; |
|
266 while (days >= (rem = __isleap(dt.tm_year) ? 366 : 365)) { |
|
267 dt.tm_year++; |
|
268 days -= rem; |
|
269 } |
|
270 while (days < 0) { |
|
271 dt.tm_year--; |
|
272 days += __isleap(dt.tm_year) ? 366 : 365; |
|
273 } |
|
274 dt.tm_mon = 1; |
|
275 while (days > __mon_yday[__isleap(dt.tm_year)][dt.tm_mon]) { |
|
276 dt.tm_mon += 1; |
|
277 } |
|
278 dt.tm_day = days - __mon_yday[__isleap(dt.tm_year)][dt.tm_mon - 1] + 1; |
|
279 |
|
280 return dt; |
|
281 } |
232 |
282 |
233 static inline IEC_TIMESPEC __date_to_timespec(int day, int month, int year) { |
283 static inline IEC_TIMESPEC __date_to_timespec(int day, int month, int year) { |
234 IEC_TIMESPEC ts; |
284 IEC_TIMESPEC ts; |
235 struct tm broken_down_time; |
285 int a4, b4, a100, b100, a400, b400; |
236 time_t epoch_seconds; |
286 int yday; |
237 |
287 int intervening_leap_days; |
238 broken_down_time.tm_sec = 0; |
288 |
239 broken_down_time.tm_min = 0; |
289 if (month < 1 || month > 12) |
240 broken_down_time.tm_hour = 0; |
290 __iec_error(); |
241 broken_down_time.tm_mday = day; /* day of month, from 1 to 31 */ |
291 |
242 broken_down_time.tm_mon = month - 1; /* month since January, in the range 0 to 11 */ |
292 yday = __mon_yday[__isleap(year)][month - 1] + day; |
243 broken_down_time.tm_year = year - 1900; /* number of years since 1900 */ |
293 |
244 broken_down_time.tm_isdst = -1; /* disable daylight savings time */ |
294 if (yday > __mon_yday[__isleap(year)][month]) |
|
295 __iec_error(); |
|
296 |
|
297 a4 = (year >> 2) - ! (year & 3); |
|
298 b4 = (EPOCH_YEAR >> 2) - ! (EPOCH_YEAR & 3); |
|
299 a100 = a4 / 25 - (a4 % 25 < 0); |
|
300 b100 = b4 / 25 - (b4 % 25 < 0); |
|
301 a400 = a100 >> 2; |
|
302 b400 = b100 >> 2; |
|
303 intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); |
245 |
304 |
246 epoch_seconds = TIMEGM(&broken_down_time); /* determine number of seconds since the epoch, i.e. Jan 1st 1970 */ |
305 ts.tv_sec = ((year - EPOCH_YEAR) * 365 + intervening_leap_days + yday - 1) * 24 * 60 * 60; |
247 |
|
248 if ((time_t)(-1) == epoch_seconds) |
|
249 __iec_error(); |
|
250 |
|
251 ts.tv_sec = epoch_seconds; |
|
252 ts.tv_nsec = 0; |
306 ts.tv_nsec = 0; |
253 |
307 |
254 return ts; |
308 return ts; |
255 } |
309 } |
256 |
310 |
514 if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN; |
568 if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN; |
515 return res; |
569 return res; |
516 } |
570 } |
517 static inline STRING __date_to_string(DATE IN){ |
571 static inline STRING __date_to_string(DATE IN){ |
518 STRING res; |
572 STRING res; |
519 struct tm* broken_down_time; |
573 tm broken_down_time; |
520 time_t seconds; |
|
521 /* D#1984-06-25 */ |
574 /* D#1984-06-25 */ |
|
575 broken_down_time = convert_seconds_to_date_and_time(IN.tv_sec); |
522 res = __INIT_STRING; |
576 res = __INIT_STRING; |
523 seconds = IN.tv_sec; |
577 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "D#%d-%2.2d-%2.2d", |
524 if (NULL == (broken_down_time = gmtime(&seconds))){ /* get the UTC (GMT) broken down time */ |
578 broken_down_time.tm_year, |
525 __iec_error(); |
579 broken_down_time.tm_mon, |
526 return (STRING){7,"D#ERROR"}; |
580 broken_down_time.tm_day); |
527 } |
|
528 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "D#%d-%2.2d-%2.2d", broken_down_time->tm_year + 1900, broken_down_time->tm_mon + 1, broken_down_time->tm_mday); |
|
529 if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN; |
581 if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN; |
530 return res; |
582 return res; |
531 } |
583 } |
532 static inline STRING __tod_to_string(TOD IN){ |
584 static inline STRING __tod_to_string(TOD IN){ |
533 STRING res; |
585 STRING res; |
534 struct tm* broken_down_time; |
586 tm broken_down_time; |
535 time_t seconds; |
587 time_t seconds; |
536 /* TOD#15:36:55.36 */ |
588 /* TOD#15:36:55.36 */ |
|
589 seconds = IN.tv_sec; |
|
590 if (seconds >= SECONDS_PER_DAY){ |
|
591 __iec_error(); |
|
592 return (STRING){9,"TOD#ERROR"}; |
|
593 } |
|
594 broken_down_time = convert_seconds_to_date_and_time(seconds); |
537 res = __INIT_STRING; |
595 res = __INIT_STRING; |
538 seconds = IN.tv_sec; |
|
539 if (NULL == (broken_down_time = gmtime(&seconds))){ /* get the UTC (GMT) broken down time */ |
|
540 __iec_error(); |
|
541 return (STRING){9,"TOD#ERROR"}; |
|
542 } |
|
543 if(IN.tv_nsec == 0){ |
596 if(IN.tv_nsec == 0){ |
544 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "TOD#%2.2d:%2.2d:%2.2d", broken_down_time->tm_hour, broken_down_time->tm_min, broken_down_time->tm_sec); |
597 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "TOD#%2.2d:%2.2d:%2.2d", |
|
598 broken_down_time.tm_hour, |
|
599 broken_down_time.tm_min, |
|
600 broken_down_time.tm_sec); |
545 }else{ |
601 }else{ |
546 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "TOD#%2.2d:%2.2d:%09.6g", broken_down_time->tm_hour, broken_down_time->tm_min, (LREAL)broken_down_time->tm_sec + (LREAL)IN.tv_nsec / 1e9); |
602 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "TOD#%2.2d:%2.2d:%09.6g", |
|
603 broken_down_time.tm_hour, |
|
604 broken_down_time.tm_min, |
|
605 (LREAL)broken_down_time.tm_sec + (LREAL)IN.tv_nsec / 1e9); |
547 } |
606 } |
548 if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN; |
607 if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN; |
549 return res; |
608 return res; |
550 } |
609 } |
551 static inline STRING __dt_to_string(DT IN){ |
610 static inline STRING __dt_to_string(DT IN){ |
552 STRING res; |
611 STRING res; |
553 struct tm* broken_down_time; |
612 tm broken_down_time; |
554 time_t seconds; |
613 time_t seconds; |
555 /* DT#1984-06-25-15:36:55.36 */ |
614 /* DT#1984-06-25-15:36:55.36 */ |
556 seconds = IN.tv_sec; |
615 broken_down_time = convert_seconds_to_date_and_time(IN.tv_sec); |
557 if (NULL == (broken_down_time = gmtime(&seconds))){ /* get the UTC (GMT) broken down time */ |
|
558 __iec_error(); |
|
559 return (STRING){8,"DT#ERROR"}; |
|
560 } |
|
561 if(IN.tv_nsec == 0){ |
616 if(IN.tv_nsec == 0){ |
562 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "DT#%d-%2.2d-%2.2d-%2.2d:%2.2d:%2.2d", |
617 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "DT#%d-%2.2d-%2.2d-%2.2d:%2.2d:%2.2d", |
563 broken_down_time->tm_year + 1900, |
618 broken_down_time.tm_year, |
564 broken_down_time->tm_mon + 1, |
619 broken_down_time.tm_mon, |
565 broken_down_time->tm_mday, |
620 broken_down_time.tm_day, |
566 broken_down_time->tm_hour, |
621 broken_down_time.tm_hour, |
567 broken_down_time->tm_min, |
622 broken_down_time.tm_min, |
568 broken_down_time->tm_sec); |
623 broken_down_time.tm_sec); |
569 }else{ |
624 }else{ |
570 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "DT#%d-%2.2d-%2.2d-%2.2d:%2.2d:%09.6g", |
625 res.len = snprintf((char*)&res.body, STR_MAX_LEN, "DT#%d-%2.2d-%2.2d-%2.2d:%2.2d:%09.6g", |
571 broken_down_time->tm_year + 1900, |
626 broken_down_time.tm_year, |
572 broken_down_time->tm_mon + 1, |
627 broken_down_time.tm_mon, |
573 broken_down_time->tm_mday, |
628 broken_down_time.tm_day, |
574 broken_down_time->tm_hour, |
629 broken_down_time.tm_hour, |
575 broken_down_time->tm_min, |
630 broken_down_time.tm_min, |
576 (LREAL)broken_down_time->tm_sec + ((LREAL)IN.tv_nsec / 1e9)); |
631 (LREAL)broken_down_time.tm_sec + ((LREAL)IN.tv_nsec / 1e9)); |
577 } |
632 } |
578 if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN; |
633 if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN; |
579 return res; |
634 return res; |
580 } |
635 } |
581 |
636 |