43 static const char* duration_str =
"duration";
64 ods_log_error(
"[%s] cannot create: allocator failed", duration_str);
132 ods_log_error(
"[%s] cannot create from string %s: create failed",
140 P = strchr(str,
'P');
142 ods_log_error(
"[%s] cannot create from string %s: P not found",
148 T = strchr(str,
'T');
149 X = strchr(str,
'Y');
151 duration->
years = atoi(str+1);
155 X = strchr(str,
'M');
156 if (X && (!T || (
size_t) (X-P) < (
size_t) (T-P))) {
157 duration->
months = atoi(str+1);
161 X = strchr(str,
'D');
163 duration->
days = atoi(str+1);
171 X = strchr(str,
'H');
173 duration->
hours = atoi(str+1);
177 X = strrchr(str,
'M');
178 if (X && T && (
size_t) (X-P) > (
size_t) (T-P)) {
179 duration->
minutes = atoi(str+1);
183 X = strchr(str,
'S');
185 duration->
seconds = atoi(str+1);
190 W = strchr(str,
'W');
198 duration->
weeks = atoi(str+1);
211 digits_in_number(time_t duration)
213 uint32_t period = (uint32_t) duration;
233 char* str = NULL, *num = NULL;
241 if (duration->
years > 0) {
242 count = count + 1 + digits_in_number(duration->
years);
245 if (duration->
months > 0) {
246 count = count + 1 + digits_in_number(duration->
months);
249 if (duration->
weeks > 0) {
250 count = count + 1 + digits_in_number(duration->
weeks);
253 if (duration->
days > 0) {
254 count = count + 1 + digits_in_number(duration->
days);
257 if (duration->
hours > 0) {
258 count = count + 1 + digits_in_number(duration->
hours);
262 count = count + 1 + digits_in_number(duration->
minutes);
267 count = count + 1 + digits_in_number(duration->
seconds);
274 str = (
char*) calloc(count,
sizeof(
char));
278 if (duration->
years > 0) {
279 count = digits_in_number(duration->
years);
280 num = (
char*) calloc(count+2,
sizeof(
char));
282 snprintf(num, count+2,
"%uY", (uint32_t) duration->
years);
283 str = strncat(str, num, count+2);
286 goto duration2string_num_calloc_failed;
289 if (duration->
months > 0) {
290 count = digits_in_number(duration->
months);
291 num = (
char*) calloc(count+2,
sizeof(
char));
293 snprintf(num, count+2,
"%uM", (uint32_t) duration->
months);
294 str = strncat(str, num, count+2);
297 goto duration2string_num_calloc_failed;
300 if (duration->
weeks > 0) {
301 count = digits_in_number(duration->
weeks);
302 num = (
char*) calloc(count+2,
sizeof(
char));
304 snprintf(num, count+2,
"%uW", (uint32_t) duration->
weeks);
305 str = strncat(str, num, count+2);
308 goto duration2string_num_calloc_failed;
311 if (duration->
days > 0) {
312 count = digits_in_number(duration->
days);
313 num = (
char*) calloc(count+2,
sizeof(
char));
315 snprintf(num, count+2,
"%uD", (uint32_t) duration->
days);
316 str = strncat(str, num, count+2);
319 goto duration2string_num_calloc_failed;
323 str = strncat(str,
"T", 1);
325 if (duration->
hours > 0) {
326 count = digits_in_number(duration->
hours);
327 num = (
char*) calloc(count+2,
sizeof(
char));
329 snprintf(num, count+2,
"%uH", (uint32_t) duration->
hours);
330 str = strncat(str, num, count+2);
333 goto duration2string_num_calloc_failed;
337 count = digits_in_number(duration->
minutes);
338 num = (
char*) calloc(count+2,
sizeof(
char));
340 snprintf(num, count+2,
"%uM", (uint32_t) duration->
minutes);
341 str = strncat(str, num, count+2);
344 goto duration2string_num_calloc_failed;
349 count = digits_in_number(duration->
seconds);
350 num = (
char*) calloc(count+2,
sizeof(
char));
352 snprintf(num, count+2,
"%uS", (uint32_t) duration->
seconds);
353 str = strncat(str, num, count+2);
356 goto duration2string_num_calloc_failed;
361 duration2string_num_calloc_failed:
362 ods_log_error(
"[%s] cannot create string: malloc error", duration_str);
380 period += (duration->
minutes)*60;
381 period += (duration->
hours)*3600;
382 period += (duration->
days)*86400;
383 period += (duration->
weeks)*86400*7;
384 period += (duration->
months)*86400*31;
385 period += (duration->
years)*86400*365;
391 duration_str, dstr?dstr:
"(null)");
405 return (a < b ? a : b);
415 return (a > b ? a : b);
426 #ifdef HAVE_ARC4RANDOM_UNIFORM
427 return (time_t) (arc4random_uniform((uint32_t) mod+1));
428 #elif HAVE_ARC4RANDOM
429 return (time_t) (arc4random() % (unsigned) mod+1);
431 return (time_t) (random() % (unsigned) mod+1);
437 static const int mdays[] = {
438 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
443 is_leap_year(
int year)
445 return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
450 leap_days(
int y1,
int y2)
454 return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
458 #ifdef ENFORCER_TIMESHIFT
464 mktime_from_utc(
const struct tm *tm)
466 int year = 1900 + tm->tm_year;
467 time_t days = 365 * ((time_t) (year - 1970)) +
468 ((time_t) leap_days(1970, year));
474 for (i = 0; i < tm->tm_mon; ++i) {
477 if (tm->tm_mon > 1 && is_leap_year(year)) {
480 days += tm->tm_mday - 1;
482 hours = days * 24 + tm->tm_hour;
483 minutes = hours * 60 + tm->tm_min;
484 seconds = minutes * 60 + tm->tm_sec;
495 timeshift2time(
const char *time)
499 time_t timeshift = 0;
502 if (strptime(time,
"%Y%m%d%H%M%S", &tm)) {
503 timeshift = mktime_from_utc(&tm);
517 #ifdef ENFORCER_TIMESHIFT
518 const char* env = getenv(
"ENFORCER_TIMESHIFT");
520 return timeshift2time(env);
548 ods_log_error(
"[%s] time_datestamp: localtime() failed", duration_str);
552 if (strftime(outstr,
sizeof(outstr), format, tmp) == 0) {
553 ods_log_error(
"[%s] time_datestamp: strftime() failed", duration_str);
557 ut = (uint32_t) strtoul(outstr, NULL, 10);
559 *str = strdup(outstr);
565 time_itoa_reverse(
char* s)
570 for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
589 s[i++] = n % 10 +
'0';
590 }
while ((n /= 10) > 0);
592 time_itoa_reverse(s);
uint32_t time_datestamp(time_t tt, const char *format, char **str)
void * allocator_alloc(allocator_type *allocator, size_t size)
duration_type * duration_create(void)
void ods_log_error(const char *format,...)
void duration_cleanup(duration_type *duration)
time_t time_maximum(time_t a, time_t b)
allocator_type * allocator_create(void *(*allocator)(size_t size), void(*deallocator)(void *))
char * duration2string(duration_type *duration)
time_t duration2time(duration_type *duration)
int duration_compare(duration_type *d1, duration_type *d2)
void allocator_cleanup(allocator_type *allocator)
void time_itoa(time_t n, char *s)
void allocator_deallocate(allocator_type *allocator, void *data)
allocator_type * allocator
duration_type * duration_create_from_string(const char *str)
time_t ods_rand(time_t mod)
time_t time_minimum(time_t a, time_t b)
void ods_log_warning(const char *format,...)