25 #include "opensync_internals.h" 32 time_t timegm(
struct tm *t)
57 return (tl - (tb - tl));
72 static char *osync_time_timestamp_remove_dash(
const char *timestamp) {
74 GString *str = g_string_new(
"");
76 len = strlen(timestamp);
78 for (i=0; i < len; i++) {
79 if (timestamp[i] ==
'-')
82 if (timestamp[i] ==
':')
85 str = g_string_append_c(str, timestamp[i]);
88 return (
char*) g_string_free(str, FALSE);
96 char *osync_time_timestamp(
const char *vtime) {
101 timestamp = osync_time_timestamp_remove_dash(vtime);
112 char *osync_time_datestamp(
const char *vtime) {
117 GString *str = g_string_new (
"");
119 tmp = osync_time_timestamp_remove_dash(vtime);
121 for (p=tmp; *p && *p !=
'T'; p++)
122 str = g_string_append_c (str, *p);
127 return (
char*) g_string_free(str, FALSE);
134 osync_bool osync_time_isdate(
const char *vtime) {
136 int year, month, day;
138 if (strstr(vtime,
"T"))
142 if (sscanf(vtime,
"%04d%02d%02d", &year, &month, &day) != 3)
152 osync_bool osync_time_isutc(
const char *vtime) {
154 if (!strstr(vtime,
"Z"))
194 struct tm *osync_time_vtime2tm(
const char *vtime) {
198 struct tm *utime = g_malloc0(
sizeof(
struct tm));
207 sscanf(vtime,
"%04d%02d%02dT%02d%02d%02d%*01c",
208 &(utime->tm_year), &(utime->tm_mon), &(utime->tm_mday),
209 &(utime->tm_hour), &(utime->tm_min), &(utime->tm_sec));
211 utime->tm_year -= 1900;
215 utime->tm_isdst = -1;
230 char *osync_time_tm2vtime(
const struct tm *time, osync_bool is_utc) {
233 GString *vtime = g_string_new(
"");
235 g_string_printf(vtime,
"%04d%02d%02dT%02d%02d%02d",
236 time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
237 time->tm_hour, time->tm_min, time->tm_sec);
240 vtime = g_string_append(vtime,
"Z");
243 return g_string_free(vtime, FALSE);
252 time_t osync_time_vtime2unix(
const char *vtime,
int offset) {
255 struct tm *utime = NULL;
259 utc = osync_time_vtime2utc(vtime, offset);
260 utime = osync_time_vtime2tm(utc);
262 timestamp = osync_time_tm2unix(utime);
276 char *osync_time_unix2vtime(
const time_t *timestamp) {
282 gmtime_r(timestamp, &utc);
283 vtime = osync_time_tm2vtime(&utc, TRUE);
294 time_t osync_time_tm2unix(
const struct tm *tmtime) {
297 struct tm *tmp = g_malloc0(
sizeof(
struct tm));
299 memcpy(tmp, tmtime,
sizeof(
struct tm));
301 timestamp = timegm(tmp);
313 struct tm *osync_time_unix2tm(
const time_t *timestamp) {
318 gmtime_r(timestamp, &tmtime);
334 int osync_time_timezone_diff(
const struct tm *time) {
337 struct tm ltime, utime;
338 unsigned int lsecs, usecs;
342 timestamp = osync_time_tm2unix(time);
346 localtime_r(×tamp, <ime);
347 gmtime_r(×tamp, &utime);
349 lsecs = 3600 * ltime.tm_hour + 60 * ltime.tm_min + ltime.tm_sec;
350 usecs = 3600 * utime.tm_hour + 60 * utime.tm_min + utime.tm_sec;
352 zonediff = lsecs - usecs;
355 if (utime.tm_mday != ltime.tm_mday) {
356 if (utime.tm_mday < ltime.tm_mday)
357 zonediff += 24 * 3600;
359 zonediff -= 24 * 3600;
373 struct tm *osync_time_tm2utc(
const struct tm *ltime,
int offset) {
376 struct tm *tmtime = g_malloc0(
sizeof(
struct tm));
378 tmtime->tm_year = ltime->tm_year;
379 tmtime->tm_mon = ltime->tm_mon;
380 tmtime->tm_mday = ltime->tm_mday;
381 tmtime->tm_hour = ltime->tm_hour;
382 tmtime->tm_min = ltime->tm_min;
383 tmtime->tm_sec = ltime->tm_sec;
386 tmtime->tm_hour -= offset / 3600;
387 tmtime->tm_min -= (offset % 3600) / 60;
389 if (tmtime->tm_hour > 23 || tmtime->tm_hour < 0) {
391 if (tmtime->tm_hour < 0) {
392 tmtime->tm_hour += 24;
393 tmtime->tm_mday -= 1;
395 tmtime->tm_hour -= 24;
396 tmtime->tm_mday += 1;
411 struct tm *osync_time_tm2localtime(
const struct tm *utime,
int offset) {
413 struct tm *tmtime = g_malloc0(
sizeof(
struct tm));
415 tmtime->tm_year = utime->tm_year;
416 tmtime->tm_mon = utime->tm_mon;
417 tmtime->tm_mday = utime->tm_mday;
418 tmtime->tm_hour = utime->tm_hour;
419 tmtime->tm_min = utime->tm_min;
420 tmtime->tm_sec = utime->tm_sec;
422 tmtime->tm_hour += offset / 3600;
423 tmtime->tm_min += (offset % 3600) / 60;
425 if (tmtime->tm_hour > 23 || tmtime->tm_hour < 0) {
427 if (tmtime->tm_hour < 0) {
428 tmtime->tm_mday -= 1;
429 tmtime->tm_hour += 24;
431 tmtime->tm_mday += 1;
432 tmtime->tm_hour -= 24;
445 char *osync_time_vtime2utc(
const char* localtime,
int offset) {
449 struct tm *tm_local = NULL, *tm_utc = NULL;
451 if (strstr(localtime,
"Z")) {
452 utc = strdup(localtime);
456 tm_local = osync_time_vtime2tm(localtime);
457 tm_utc = osync_time_tm2utc(tm_local, offset);
458 utc = osync_time_tm2vtime(tm_utc, TRUE);
474 char *osync_time_vtime2localtime(
const char* utc,
int offset) {
476 char *localtime = NULL;
477 struct tm *tm_local = NULL, *tm_utc = NULL;
479 if (!strstr(utc,
"Z")) {
480 localtime = strdup(utc);
484 tm_utc = osync_time_vtime2tm(utc);
485 tm_local = osync_time_tm2localtime(tm_utc, offset);
486 localtime = osync_time_tm2vtime(tm_local, FALSE);
502 const char *_time_attr[] = {
518 static void _convert_time_field(GString *entry,
const char *field, osync_bool toUTC) {
522 char *new_stamp = NULL;
524 GString *stamp = g_string_new(
"");
526 if ((res = strstr(entry->str, field))) {
527 res += strlen(field);
529 for (i=0; res[i] !=
'\n' && res[i] !=
'\r'; i++)
530 stamp = g_string_append_c(stamp, res[i]);
532 gssize pos = res - entry->str;
533 entry = g_string_erase(entry, pos, i);
536 struct tm *tm_stamp = osync_time_vtime2tm(stamp->str);
537 tzdiff = osync_time_timezone_diff(tm_stamp);
541 new_stamp = osync_time_vtime2utc(stamp->str, tzdiff);
543 new_stamp = osync_time_vtime2localtime(stamp->str, tzdiff);
545 entry = g_string_insert(entry, pos, new_stamp);
556 char *_convert_entry(
const char *vcal, osync_bool toUTC) {
559 GString *new_entry = g_string_new(vcal);
561 for (i=0; _time_attr[i] != NULL; i++)
562 _convert_time_field(new_entry, _time_attr[i], toUTC);
564 return g_string_free(new_entry, FALSE);
572 char *osync_time_vcal2localtime(
const char *vcal) {
574 return _convert_entry(vcal, FALSE);
582 char *osync_time_vcal2utc(
const char *vcal) {
584 return _convert_entry(vcal, TRUE);
593 char *osync_time_sec2alarmdu(
int seconds) {
601 tmp = g_strdup(
"PT0S");
606 prefix = g_strdup(
"P");
608 prefix = g_strdup(
"-P");
613 if (!(seconds % (3600 * 24))) {
614 tmp = g_strdup_printf(
"%s%iD", prefix, seconds / (3600 * 24));
619 if (!(seconds % 3600)) {
620 tmp = g_strdup_printf(
"%sT%iH", prefix, seconds / 3600);
625 if (!(seconds % 60) && seconds < 3600) {
626 tmp = g_strdup_printf(
"%sT%iM", prefix, seconds / 60);
632 tmp = g_strdup_printf(
"%sT%iS", prefix, seconds);
637 tmp = g_strdup_printf(
"%sT%iM", prefix, seconds / 60);
640 tmp = g_strdup_printf(
"%sT%iH%iM", prefix, seconds / 3600,
641 (seconds % 3600) / 60);
643 if (seconds > (3600 * 24))
644 tmp = g_strdup_printf(
"%s%iDT%iH%iM", prefix, seconds / (3600 * 24),
645 seconds % (3600 * 24) / 3600,
646 ((seconds % (3600 * 24) % 3600)) / 60);
663 int osync_time_alarmdu2sec(
const char *alarm) {
670 int days = 0, weeks = 0, hours = 0, minutes = 0, seconds = 0;
672 for (i=0; i < (int) strlen(alarm); i++) {
714 sscanf((
char*)(alarm+i),
"%d",&digits);
720 secs = (weeks * 7 * 24 * 3600) + (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
737 int osync_time_str2wday(
const char *swday) {
741 if (!strcmp(swday,
"SU"))
743 else if (!strcmp(swday,
"MO"))
745 else if (!strcmp(swday,
"TU"))
747 else if (!strcmp(swday,
"WE"))
749 else if (!strcmp(swday,
"TH"))
751 else if (!strcmp(swday,
"FR"))
753 else if (!strcmp(swday,
"SA"))
769 struct tm *osync_time_relative2tm(
const char *byday,
const int bymonth,
const int year) {
771 struct tm *datestamp = g_malloc0(
sizeof(
struct tm));
773 int first_wday = 0, last_wday = 0;
774 int daymod, mday, searched_wday;
776 sscanf(byday,
"%d%s", &daymod, weekday);
779 searched_wday = osync_time_str2wday(weekday);
781 datestamp->tm_year = year - 1900;
782 datestamp->tm_mon = bymonth - 1;
783 datestamp->tm_mday = 0;
784 datestamp->tm_hour = 0;
785 datestamp->tm_min = 0;
786 datestamp->tm_sec = 0;
787 datestamp->tm_isdst = -1;
789 for (mday = 0; mday <= 31; mday++) {
790 datestamp->tm_mday = mday;
793 if (datestamp->tm_wday == searched_wday) {
795 first_wday = searched_wday;
797 last_wday = searched_wday;
802 datestamp->tm_mday = first_wday + (7 * (daymod - 1));
804 datestamp->tm_mday = last_wday - (7 * (daymod - 1));
816 int osync_time_utcoffset2sec(
const char *offset) {
820 int seconds = 0, sign = 1;
821 int hours = 0, minutes = 0;
823 sscanf(offset,
"%c%2d%2d", &csign, &hours, &minutes);
828 seconds = (hours * 3600 + minutes * 60) * sign;
841 struct tm *osync_time_dstchange(xmlNode *dstNode) {
844 struct tm *dst_change = NULL, *tm_started = NULL;
845 char *started = NULL, *rule = NULL, *byday = NULL;
847 xmlNode *current = osxml_get_node(dstNode,
"DateStarted");
848 started = (
char*) xmlNodeGetContent(current);
849 tm_started = osync_time_vtime2tm(started);
853 current = osxml_get_node(dstNode,
"RecurrenceRule");
854 current = current->children;
857 rule = (
char *) xmlNodeGetContent(current);
859 if (strstr(rule,
"BYDAY="))
860 byday = g_strdup(rule + 6);
861 else if (strstr(rule,
"BYMONTH="))
862 sscanf(rule,
"BYMONTH=%d", &month);
866 current = current->next;
869 dst_change = osync_time_relative2tm(byday, month, tm_started->tm_year + 1900);
873 dst_change->tm_hour = tm_started->tm_hour;
874 dst_change->tm_min = tm_started->tm_min;
887 osync_bool osync_time_isdst(
const char *vtime, xmlNode *tzid) {
897 struct tm *std_changetime, *dst_changetime;
898 time_t dstStamp, stdStamp;
899 xmlNode *current = NULL;
901 sscanf(vtime,
"%4d%*2d%*2dT%*2d%*d%*2d%*c", &year);
907 timestamp = osync_time_vtime2unix(vtime, 0);
910 current = osxml_get_node(tzid,
"Standard");
911 std_changetime = osync_time_dstchange(current);
913 current = osxml_get_node(tzid,
"DaylightSavings");
914 dst_changetime = osync_time_dstchange(current);
917 dstStamp = osync_time_tm2unix(dst_changetime);
918 stdStamp = osync_time_tm2unix(std_changetime);
920 if (timestamp > stdStamp && timestamp < dstStamp) {
936 int osync_time_tzoffset(
const char *vtime, xmlNode *tz) {
942 xmlNode *current = NULL;
944 if (osync_time_isdst(vtime, tz))
945 current = osxml_get_node(tz,
"DaylightSavings");
947 current = osxml_get_node(tz,
"Standard");
949 offset = osxml_find_node(current,
"TZOffsetFrom");
950 seconds = osync_time_utcoffset2sec(offset);
961 char *osync_time_tzid(xmlNode *tz) {
966 id = osxml_find_node(tz,
"TimezoneID");
977 char *osync_time_tzlocation(xmlNode *tz) {
980 char *location = NULL;
982 location = osxml_find_node(tz,
"TimezoneLocation");
994 xmlNode *osync_time_tzinfo(xmlNode *root,
const char *tzid) {
999 char *tzinfo_tzid = NULL;
1002 xmlNodeSet *nodes = NULL;
1003 xmlXPathObject *xobj = NULL;
1006 xobj = osxml_get_nodeset(root->doc,
"/vcal/Timezone");
1007 nodes = xobj->nodesetval;
1008 numnodes = (nodes) ? nodes->nodeNr : 0;
1016 for (i=0; i < numnodes; i++) {
1017 tz = nodes->nodeTab[i];
1018 tzinfo_tzid = osync_time_tzid(tz);
1021 g_free(tzinfo_tzid);
1026 if (!strcmp(tzinfo_tzid, tzid))
1030 g_free(tzinfo_tzid);
1040 osync_trace(
TRACE_EXIT,
"%s: No matching Timezone node found. Seems to be a be a floating timestamp.", __func__);
1050 char *osync_time_tzlocal2utc(xmlNode *root,
const char *field) {
1054 char *utc = NULL, *field_tzid = NULL, *vtime = NULL;
1065 field_tzid = osync_time_tzid(root);
1071 tz = osync_time_tzinfo(root, field_tzid);
1077 vtime = osxml_find_node(root,
"Content");
1080 offset = osync_time_tzoffset(vtime, tz);
1081 struct tm *ttm = osync_time_vtime2tm(vtime);
1082 ttm->tm_hour -= offset / 3600;
1083 ttm->tm_min -= (offset % 3600) / 60;
1085 utc = osync_time_tm2vtime(ttm, TRUE);
void osync_trace(OSyncTraceType type, const char *message,...)
Used for tracing the application.