libamxc  1.10.3
C Generic Data Containers
amxc_timestamp.c File Reference
#include <unistd.h>
#include <sys/time.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#include <amxc/amxc_timestamp.h>
#include <amxc/amxc_macros.h>

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 
#define EPOCH   INT64_C(62135683200) /* 1970-01-01T00:00:00 */
 
#define MIN_SEC   INT64_C(-62135596800) /* 0001-01-01T00:00:00 */
 
#define MAX_SEC   INT64_C(253402300799) /* 9999-12-31T23:59:59 */
 
#define RDN_OFFSET   INT64_C(62135683200) /* 1970-01-01T00:00:00 */
 

Functions

static int leap_year (uint16_t y)
 
static unsigned char month_days (uint16_t y, uint16_t m)
 
static int parse_2d (const unsigned char *const p, size_t i, uint16_t *vp)
 
static int parse_4d (const unsigned char *const p, size_t i, uint16_t *vp)
 
static void rdn_to_ymd (uint32_t rdn, uint16_t *yp, uint16_t *mp, uint16_t *dp)
 
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 int timestamp_to_tm (const amxc_ts_t *tsp, struct tm *tmp, const bool local)
 
int amxc_ts_now (amxc_ts_t *tsp)
 Takes current time as unix epoch time. More...
 
static int amxc_ts_parse_date (const unsigned char *cur, uint16_t *year, uint16_t *month, uint16_t *day)
 
static int amxc_ts_parse_time (const unsigned char *cur, uint16_t *hour, uint16_t *min, uint16_t *sec)
 
static int amxc_ts_parse_offset (const unsigned char *cur, const unsigned char *end, int16_t *offset)
 
int amxc_ts_parse (amxc_ts_t *tsp, const char *str, size_t len)
 Transforms the given string in to unix epoch time. More...
 
size_t amxc_ts_format (const amxc_ts_t *tsp, char *dst, size_t len)
 Transforms unix epoch time to a string. More...
 
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. More...
 
int amxc_ts_compare (const amxc_ts_t *tsp1, const amxc_ts_t *tsp2)
 Checks if tsp1 comes after tsp2. More...
 
bool amxc_ts_is_valid (const amxc_ts_t *tsp)
 Checks if a timestamp is valid. More...
 
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. More...
 
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. More...
 
int amxc_ts_to_local (amxc_ts_t *tsp)
 Adds the local time offset to the timestamp structure. More...
 
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. More...
 

Variables

static const uint32_t Pow10 [10]
 
static const uint16_t DayOffset [13]
 

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 82 of file amxc_timestamp.c.

◆ EPOCH

#define EPOCH   INT64_C(62135683200) /* 1970-01-01T00:00:00 */

Definition at line 95 of file amxc_timestamp.c.

◆ MAX_SEC

#define MAX_SEC   INT64_C(253402300799) /* 9999-12-31T23:59:59 */

Definition at line 97 of file amxc_timestamp.c.

◆ MIN_SEC

#define MIN_SEC   INT64_C(-62135596800) /* 0001-01-01T00:00:00 */

Definition at line 96 of file amxc_timestamp.c.

◆ RDN_OFFSET

#define RDN_OFFSET   INT64_C(62135683200) /* 1970-01-01T00:00:00 */

Definition at line 98 of file amxc_timestamp.c.

Function Documentation

◆ amxc_ts_parse_date()

static int amxc_ts_parse_date ( const unsigned char *  cur,
uint16_t *  year,
uint16_t *  month,
uint16_t *  day 
)
static

Definition at line 319 of file amxc_timestamp.c.

322  {
323  int retval = 1;
324  when_true(parse_4d(cur, 0, year) || *year < 1, exit);
325  when_true(parse_2d(cur, 5, month) || *month < 1 || *month > 12, exit);
326  when_true(parse_2d(cur, 8, day) || *day < 1 || *day > 31, exit);
327 
328  retval = 0;
329 exit:
330  return retval;
331 }
#define when_true(x, l)
Definition: amxc_macros.h:134
static int parse_2d(const unsigned char *const p, size_t i, uint16_t *vp)
static int parse_4d(const unsigned char *const p, size_t i, uint16_t *vp)

◆ amxc_ts_parse_offset()

static int amxc_ts_parse_offset ( const unsigned char *  cur,
const unsigned char *  end,
int16_t *  offset 
)
static

Definition at line 347 of file amxc_timestamp.c.

349  {
350  int retval = -1;
351  uint16_t hour;
352  uint16_t min;
353  unsigned char ch = *cur;
354  when_true(cur + 6 < end || !(ch == '+' || ch == '-') || cur[3] != ':', exit);
355 
356  when_true(parse_2d(cur + 1, 0, &hour) || hour > 23 ||
357  parse_2d(cur + 1, 3, &min) || min > 59, exit);
358 
359  *offset = hour * 60 + min;
360  if(ch == '-') {
361  *offset *= -1;
362  }
363 
364  retval = 0;
365 exit:
366  return retval;
367 }

◆ amxc_ts_parse_time()

static int amxc_ts_parse_time ( const unsigned char *  cur,
uint16_t *  hour,
uint16_t *  min,
uint16_t *  sec 
)
static

Definition at line 333 of file amxc_timestamp.c.

336  {
337  int retval = 1;
338  when_true(parse_2d(cur, 11, hour) || *hour > 23, exit);
339  when_true(parse_2d(cur, 14, min) || *min > 59, exit);
340  when_true(parse_2d(cur, 17, sec) || *sec > 59, exit);
341 
342  retval = 0;
343 exit:
344  return retval;
345 }

◆ leap_year()

static int leap_year ( uint16_t  y)
static

Definition at line 108 of file amxc_timestamp.c.

108  {
109  return ((y & 3) == 0 && (y % 100 != 0 || y % 400 == 0));
110 }

◆ month_days()

static unsigned char month_days ( uint16_t  y,
uint16_t  m 
)
static

Definition at line 112 of file amxc_timestamp.c.

112  {
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}
116  };
117  return days[m == 2 && leap_year(y)][m];
118 }
static int leap_year(uint16_t y)

◆ parse_2d()

static int parse_2d ( const unsigned char *const  p,
size_t  i,
uint16_t *  vp 
)
static

Definition at line 120 of file amxc_timestamp.c.

120  {
121  unsigned char d0, d1;
122  if(((d0 = p[i + 0] - '0') > 9) ||
123  ((d1 = p[i + 1] - '0') > 9)) {
124  return 1;
125  }
126  *vp = d0 * 10 + d1;
127  return 0;
128 }

◆ parse_4d()

static int parse_4d ( const unsigned char *const  p,
size_t  i,
uint16_t *  vp 
)
static

Definition at line 130 of file amxc_timestamp.c.

130  {
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)) {
136  return 1;
137  }
138  *vp = d0 * 1000 + d1 * 100 + d2 * 10 + d3;
139  return 0;
140 }

◆ rdn_to_struct_tm()

static void rdn_to_struct_tm ( uint32_t  rdn,
struct tm *  tmp 
)
static

Definition at line 248 of file amxc_timestamp.c.

248  {
249  uint32_t Z, H, A, B;
250  uint16_t C, y, m, d;
251 
252  Z = rdn + 306;
253  H = 100 * Z - 25;
254  A = H / 3652425;
255  B = A - (A >> 2);
256  y = (100 * B + H) / 36525;
257  C = B + Z - (1461 * y >> 2);
258  m = (535 * C + 48950) >> 14;
259  if(m > 12) {
260  d = C - 306, y++, m -= 12;
261  } else {
262  d = C + 59 + ((y & 3) == 0 && (y % 100 != 0 || y % 400 == 0));
263  }
264 
265  tmp->tm_mday = C - DayOffset[m]; /* Day of month [1,31] */
266  tmp->tm_mon = m - 1; /* Month of year [0,11] */
267  tmp->tm_year = y - 1900; /* Years since 1900 */
268  tmp->tm_wday = rdn % 7; /* Day of week [0,6] (Sunday =0) */
269  tmp->tm_yday = d - 1; /* Day of year [0,365] */
270 }
static const uint16_t DayOffset[13]

◆ rdn_to_ymd()

static void rdn_to_ymd ( uint32_t  rdn,
uint16_t *  yp,
uint16_t *  mp,
uint16_t *  dp 
)
static

Definition at line 143 of file amxc_timestamp.c.

143  {
144  uint32_t Z, H, A, B;
145  uint16_t y, m, d;
146 
147  Z = rdn + 306;
148  H = 100 * Z - 25;
149  A = H / 3652425;
150  B = A - (A >> 2);
151  y = (100 * B + H) / 36525;
152  d = B + Z - (1461 * y >> 2);
153  m = (535 * d + 48950) >> 14;
154  if(m > 12) {
155  y++, m -= 12;
156  }
157 
158  *yp = y;
159  *mp = m;
160  *dp = d - DayOffset[m];
161 }

◆ timestamp_format_internal()

static size_t timestamp_format_internal ( char *  dst,
size_t  len,
const amxc_ts_t tsp,
const int  precision 
)
static

Definition at line 163 of file amxc_timestamp.c.

166  {
167  unsigned char* p;
168  uint64_t sec;
169  uint32_t rdn, v;
170  uint16_t y, m, d;
171  size_t dlen;
172 
173  dlen = sizeof("YYYY-MM-DDThh:mm:ssZ") - 1;
174  if(tsp->offset) {
175  dlen += 5; /* hh:mm */
176  }
177  if(precision) {
178  dlen += 1 + precision;
179  }
180  if(dlen >= len) {
181  return 0;
182  }
183  sec = tsp->sec + tsp->offset * 60 + EPOCH;
184  rdn = sec / 86400;
185 
186  rdn_to_ymd(rdn, &y, &m, &d);
187 
188  /*
189  * 1
190  * 0123456789012345678
191  * YYYY-MM-DDThh:mm:ss
192  */
193  p = (unsigned char*) dst;
194  v = sec % 86400;
195  p[18] = '0' + (v % 10); v /= 10;
196  p[17] = '0' + (v % 6); v /= 6;
197  p[16] = ':';
198  p[15] = '0' + (v % 10); v /= 10;
199  p[14] = '0' + (v % 6); v /= 6;
200  p[13] = ':';
201  p[12] = '0' + (v % 10); v /= 10;
202  p[11] = '0' + (v % 10);
203  p[10] = 'T';
204  p[ 9] = '0' + (d % 10); d /= 10;
205  p[ 8] = '0' + (d % 10);
206  p[ 7] = '-';
207  p[ 6] = '0' + (m % 10); m /= 10;
208  p[ 5] = '0' + (m % 10);
209  p[ 4] = '-';
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);
214  p += 19;
215 
216  if(precision) {
217  v = tsp->nsec / Pow10[9 - precision];
218  for(int i = precision; i > 0; i--) {
219  p[i] = '0' + (v % 10);
220  if(i > 1) {
221  v /= 10;
222  }
223  }
224  p[0] = '.';
225  p += 1 + precision;
226  }
227 
228  if(!tsp->offset) {
229  *p++ = 'Z';
230  } else {
231  if(tsp->offset < 0) {
232  p[0] = '-', v = -tsp->offset;
233  } else {
234  p[0] = '+', v = tsp->offset;
235  }
236  p[5] = '0' + (v % 10); v /= 10;
237  p[4] = '0' + (v % 6); v /= 6;
238  p[3] = ':';
239  p[2] = '0' + (v % 10); v /= 10;
240  p[1] = '0' + (v % 10);
241  p += 6;
242  }
243  *p = 0;
244  return dlen;
245 }
#define EPOCH
static const uint32_t Pow10[10]
static void rdn_to_ymd(uint32_t rdn, uint16_t *yp, uint16_t *mp, uint16_t *dp)
int32_t nsec
int16_t offset

◆ timestamp_to_tm()

static int timestamp_to_tm ( const amxc_ts_t tsp,
struct tm *  tmp,
const bool  local 
)
static

Definition at line 272 of file amxc_timestamp.c.

274  {
275  uint64_t sec;
276  uint32_t rdn, sod;
277  int retval = -1;
278 
279  when_null(tsp, exit);
280  when_null(tmp, exit);
281  when_true(!amxc_ts_is_valid(tsp), exit);
282 
283  sec = tsp->sec + RDN_OFFSET;
284  if(local) {
285  sec += tsp->offset * 60;
286  }
287  rdn = sec / 86400;
288  sod = sec % 86400;
289 
290  rdn_to_struct_tm(rdn, tmp);
291  tmp->tm_sec = sod % 60; sod /= 60;
292  tmp->tm_min = sod % 60; sod /= 60;
293  tmp->tm_hour = sod;
294 
295  retval = 0;
296 
297 exit:
298  return retval;
299 }
#define when_null(x, l)
Definition: amxc_macros.h:126
#define RDN_OFFSET
static void rdn_to_struct_tm(uint32_t rdn, struct tm *tmp)
bool amxc_ts_is_valid(const amxc_ts_t *tsp)
Checks if a timestamp is valid.

Variable Documentation

◆ DayOffset

const uint16_t DayOffset[13]
static
Initial value:
= {
0, 306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275
}

Definition at line 104 of file amxc_timestamp.c.

◆ Pow10

const uint32_t Pow10[10]
static
Initial value:
= {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
}

Definition at line 100 of file amxc_timestamp.c.