95 #define EPOCH INT64_C(62135683200)
96 #define MIN_SEC INT64_C(-62135596800)
97 #define MAX_SEC INT64_C(253402300799)
98 #define RDN_OFFSET INT64_C(62135683200)
101 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
105 0, 306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275
109 return ((y & 3) == 0 && (y % 100 != 0 || y % 400 == 0));
113 static const unsigned char days[2][13] = {
114 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
115 {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
120 static int parse_2d(
const unsigned char*
const p,
size_t i, uint16_t* vp) {
121 unsigned char d0, d1;
122 if(((d0 = p[i + 0] -
'0') > 9) ||
123 ((d1 = p[i + 1] -
'0') > 9)) {
130 static int parse_4d(
const unsigned char*
const p,
size_t i, uint16_t* vp) {
131 unsigned char d0, d1, d2, d3;
132 if(((d0 = p[i + 0] -
'0') > 9) ||
133 ((d1 = p[i + 1] -
'0') > 9) ||
134 ((d2 = p[i + 2] -
'0') > 9) ||
135 ((d3 = p[i + 3] -
'0') > 9)) {
138 *vp = d0 * 1000 + d1 * 100 + d2 * 10 + d3;
143 static void rdn_to_ymd(uint32_t rdn, uint16_t* yp, uint16_t* mp, uint16_t* dp) {
151 y = (100 * B + H) / 36525;
152 d = B + Z - (1461 * y >> 2);
153 m = (535 * d + 48950) >> 14;
166 const int precision) {
173 dlen =
sizeof(
"YYYY-MM-DDThh:mm:ssZ") - 1;
178 dlen += 1 + precision;
193 p = (
unsigned char*) dst;
195 p[18] =
'0' + (v % 10); v /= 10;
196 p[17] =
'0' + (v % 6); v /= 6;
198 p[15] =
'0' + (v % 10); v /= 10;
199 p[14] =
'0' + (v % 6); v /= 6;
201 p[12] =
'0' + (v % 10); v /= 10;
202 p[11] =
'0' + (v % 10);
204 p[ 9] =
'0' + (d % 10); d /= 10;
205 p[ 8] =
'0' + (d % 10);
207 p[ 6] =
'0' + (m % 10); m /= 10;
208 p[ 5] =
'0' + (m % 10);
210 p[ 3] =
'0' + (y % 10); y /= 10;
211 p[ 2] =
'0' + (y % 10); y /= 10;
212 p[ 1] =
'0' + (y % 10); y /= 10;
213 p[ 0] =
'0' + (y % 10);
218 for(
int i = precision; i > 0; i--) {
219 p[i] =
'0' + (v % 10);
232 p[0] =
'-', v = -tsp->
offset;
234 p[0] =
'+', v = tsp->
offset;
236 p[5] =
'0' + (v % 10); v /= 10;
237 p[4] =
'0' + (v % 6); v /= 6;
239 p[2] =
'0' + (v % 10); v /= 10;
240 p[1] =
'0' + (v % 10);
256 y = (100 * B + H) / 36525;
257 C = B + Z - (1461 * y >> 2);
258 m = (535 * C + 48950) >> 14;
260 d = C - 306, y++, m -= 12;
262 d = C + 59 + ((y & 3) == 0 && (y % 100 != 0 || y % 400 == 0));
267 tmp->tm_year = y - 1900;
268 tmp->tm_wday = rdn % 7;
269 tmp->tm_yday = d - 1;
291 tmp->tm_sec = sod % 60; sod /= 60;
292 tmp->tm_min = sod % 60; sod /= 60;
303 struct timespec ts = {0, 0};
306 retval = clock_gettime(CLOCK_REALTIME, &ts);
307 tsp->
sec = ts.tv_sec;
308 tsp->
nsec = ts.tv_nsec;
316 return retval ? -1 : 0;
348 const unsigned char* end,
353 unsigned char ch = *cur;
354 when_true(cur + 6 < end || !(ch ==
'+' || ch ==
'-') || cur[3] !=
':', exit);
357 parse_2d(cur + 1, 3, &min) || min > 59, exit);
359 *offset = hour * 60 + min;
373 const unsigned char* cur, * end;
375 uint16_t year, month, day, hour, min, sec;
376 uint32_t rdn, sod, nsec;
387 cur = (
const unsigned char*) str;
388 when_true(cur[4] !=
'-' || cur[7] !=
'-' ||
389 cur[13] !=
':' || cur[16] !=
':', exit);
392 when_true(!(ch ==
'T' || ch ==
' ' || ch ==
't'), exit);
401 rdn = (1461 * year) / 4 - year / 100 + year / 400 +
DayOffset[month] + day - 306;
402 sod = hour * 3600 + min * 60 + sec;
409 const unsigned char* start;
413 for(; cur < end; cur++) {
414 const unsigned char digit = *cur -
'0';
418 nsec = nsec * 10 + digit;
421 ndigits = cur - start;
422 when_true(ndigits < 1 || ndigits > 9, exit);
424 nsec *=
Pow10[9 - ndigits];
431 if(!((ch ==
'Z') || (ch ==
'z'))) {
438 tsp->
sec = ((int64_t) rdn - 719163) * 86400 + sod - offset * 60;
476 if((f % 1000000) == 0) {
478 }
else if((f % 1000) == 0) {
510 if(tsp1->
sec < tsp2->
sec) {
513 if(tsp1->
sec > tsp2->
sec) {
534 ( tsp->
nsec < 0) || ( tsp->
nsec > 999999999) ||
555 time_t rawtime = time(NULL);
556 struct tm* ptm = gmtime(&rawtime);
563 ptm = localtime(&rawtime);
567 tsp->
offset = (rawtime - gmt + (ptm->tm_isdst ? 3600 : 0)) / 60;
#define when_failed(x, l)
static int parse_2d(const unsigned char *const p, size_t i, uint16_t *vp)
static int amxc_ts_parse_offset(const unsigned char *cur, const unsigned char *end, int16_t *offset)
static const uint16_t DayOffset[13]
static const uint32_t Pow10[10]
static unsigned char month_days(uint16_t y, uint16_t m)
static int timestamp_to_tm(const amxc_ts_t *tsp, struct tm *tmp, const bool local)
static int amxc_ts_parse_date(const unsigned char *cur, uint16_t *year, uint16_t *month, uint16_t *day)
static size_t timestamp_format_internal(char *dst, size_t len, const amxc_ts_t *tsp, const int precision)
static void rdn_to_struct_tm(uint32_t rdn, struct tm *tmp)
static void rdn_to_ymd(uint32_t rdn, uint16_t *yp, uint16_t *mp, uint16_t *dp)
static int leap_year(uint16_t y)
static int parse_4d(const unsigned char *const p, size_t i, uint16_t *vp)
static int amxc_ts_parse_time(const unsigned char *cur, uint16_t *hour, uint16_t *min, uint16_t *sec)
Ambiorix timestamp header file.
size_t amxc_ts_format(const amxc_ts_t *tsp, char *dst, size_t len)
Transforms unix epoch time to a string.
int amxc_ts_compare(const amxc_ts_t *tsp1, const amxc_ts_t *tsp2)
Checks if tsp1 comes after tsp2.
int amxc_ts_from_tm(amxc_ts_t *const tsp, struct tm *tmp)
Converts a broken down time in a struct tm to a timestamp structure.
int amxc_ts_to_local(amxc_ts_t *tsp)
Adds the local time offset to the timestamp structure.
int amxc_ts_parse(amxc_ts_t *tsp, const char *str, size_t len)
Transforms the given string in to unix epoch time.
bool amxc_ts_is_valid(const amxc_ts_t *tsp)
Checks if a timestamp is valid.
size_t amxc_ts_format_precision(const amxc_ts_t *tsp, char *dst, size_t len, int precision)
Transforms unix epoch time to a string.
int amxc_ts_to_tm_utc(const amxc_ts_t *tsp, struct tm *tmp)
Converts timestamp in unix epoch time to a struct tm type in UTC time.
int amxc_ts_now(amxc_ts_t *tsp)
Takes current time as unix epoch time.
int amxc_ts_to_tm_local(const amxc_ts_t *tsp, struct tm *tmp)
Converts timestamp in unix epoch time to a struct tm type in local time.
The timestamp structure (unix epoch time).