• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

opensync/opensync_time.c

00001 /*
00002  * libopensync - A synchronization framework
00003  * Copyright (C) 2004-2005  Armin Bauer <armin.bauer@opensync.org>
00004  * Copyright (C) 2006 Daniel Gollub <dgollub@suse.de>
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  * 
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00019  * 
00020  */
00021 
00022 #include <time.h>
00023 
00024 #include "opensync.h"
00025 #include "opensync_internals.h"
00026 
00027 /*
00028  * On solaris no timegm function exists,
00029  * we must implement it here
00030  */
00031 #ifdef SOLARIS
00032 time_t timegm(struct tm *t)
00033 {
00034         time_t tl, tb;
00035         struct tm *tg;
00036 
00037         tl = mktime (t);
00038         if (tl == -1)
00039         {
00040                 t->tm_hour--;
00041                 tl = mktime (t);
00042                 if (tl == -1)
00043                         return -1; /* can't deal with output from strptime */
00044                 tl += 3600;
00045         }
00046         tg = gmtime (&tl);
00047         tg->tm_isdst = 0;
00048         tb = mktime (tg);
00049         if (tb == -1)
00050         {
00051                 tg->tm_hour--;
00052                 tb = mktime (tg);
00053                 if (tb == -1)
00054                         return -1; /* can't deal with output from gmtime */
00055                 tb += 3600;
00056         }
00057         return (tl - (tb - tl));
00058 }
00059 #endif
00060 
00061 /* Floating Timestamps...... (handle tzid!) */
00062 
00063 /* 
00064  * Time formatting helper
00065  */
00066 
00072 static char *osync_time_timestamp_remove_dash(const char *timestamp) {
00073         int i, len;
00074         GString *str = g_string_new("");
00075 
00076         len = strlen(timestamp);
00077 
00078         for (i=0; i < len; i++) {
00079                 if (timestamp[i] == '-')
00080                         continue;
00081 
00082                 if (timestamp[i] == ':')
00083                         continue;
00084 
00085                 str = g_string_append_c(str, timestamp[i]);
00086         }
00087 
00088         return (char*) g_string_free(str, FALSE);
00089 }
00090 
00096 char *osync_time_timestamp(const char *vtime) {
00097         osync_trace(TRACE_ENTRY, "%s(%s)", __func__, vtime);
00098 
00099         char *timestamp;
00100 
00101         timestamp = osync_time_timestamp_remove_dash(vtime);
00102 
00103         osync_trace(TRACE_EXIT, "%s: %s", __func__, timestamp);
00104         return timestamp;
00105 }
00106 
00112 char *osync_time_datestamp(const char *vtime) {
00113         osync_trace(TRACE_ENTRY, "%s(%s)", __func__, vtime);
00114 
00115         char *tmp;
00116         const char *p;
00117         GString *str = g_string_new ("");
00118 
00119         tmp = osync_time_timestamp_remove_dash(vtime); 
00120 
00121         for (p=tmp; *p && *p != 'T'; p++)
00122                 str = g_string_append_c (str, *p);
00123 
00124         free(tmp);
00125 
00126         osync_trace(TRACE_EXIT, "%s: %s", __func__, str->str);
00127         return (char*) g_string_free(str, FALSE);
00128 }
00129 
00134 osync_bool osync_time_isdate(const char *vtime) {
00135 
00136         int year, month, day;
00137 
00138         if (strstr(vtime, "T"))
00139                 return FALSE;
00140 
00141         /* YYYYMMDD */
00142         if (sscanf(vtime, "%04d%02d%02d", &year, &month, &day) != 3)
00143                 return FALSE;
00144 
00145         return TRUE;
00146 }
00147 
00152 osync_bool osync_time_isutc(const char *vtime) {
00153 
00154         if (!strstr(vtime, "Z"))
00155                 return FALSE;
00156 
00157         return TRUE;
00158 }
00159 
00172 /*
00173 char *osync_time_set_vtime(const char *vtime, const char *time, osync_bool is_utc) {
00174         osync_trace(TRACE_ENTRY, "%s(%s, %s)", __func__, vtime, time);
00175 
00176         char *tmp = NULL;
00177         
00178         // TODO
00179 
00180         osync_trace(TRACE_EXIT, "%s: %s", __func__, tmp);
00181         return tmp;
00182 }
00183 */
00184 
00185 /*
00186  * Timetype helper  
00187  */
00188 
00194 struct tm *osync_time_vtime2tm(const char *vtime) {
00195 
00196         osync_trace(TRACE_ENTRY, "%s(%s)", __func__, vtime);
00197 
00198         struct tm *utime = g_malloc0(sizeof(struct tm));
00199 
00200         utime->tm_year = 0;
00201         utime->tm_mon = 0;
00202         utime->tm_mday = 0;
00203         utime->tm_hour = 0;
00204         utime->tm_min = 0;
00205         utime->tm_sec = 0;
00206 
00207         sscanf(vtime, "%04d%02d%02dT%02d%02d%02d%*01c",
00208                         &(utime->tm_year), &(utime->tm_mon), &(utime->tm_mday),
00209                         &(utime->tm_hour), &(utime->tm_min), &(utime->tm_sec));
00210 
00211         utime->tm_year -= 1900;
00212         utime->tm_mon -= 1;
00213 
00214         /* isdst is handled by tz offset calcualtion */
00215         utime->tm_isdst = -1;
00216 
00217         osync_trace(TRACE_EXIT, "%s", __func__);
00218         return utime;
00219 }
00220 
00230 char *osync_time_tm2vtime(const struct tm *time, osync_bool is_utc) {
00231 
00232         osync_trace(TRACE_ENTRY, "%s(%p, %i)", __func__, time, is_utc);
00233         GString *vtime = g_string_new("");
00234 
00235         g_string_printf(vtime, "%04d%02d%02dT%02d%02d%02d",
00236                                 time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
00237                                 time->tm_hour, time->tm_min, time->tm_sec);
00238 
00239         if (is_utc)
00240                 vtime = g_string_append(vtime, "Z");
00241 
00242         osync_trace(TRACE_EXIT, "%s: %s", __func__, vtime->str);
00243         return g_string_free(vtime, FALSE);
00244 }
00245 
00252 time_t osync_time_vtime2unix(const char *vtime, int offset) {
00253 
00254         osync_trace(TRACE_ENTRY, "%s(%s, %i)", __func__, vtime, offset);
00255         struct tm *utime = NULL; 
00256         time_t timestamp;
00257         char *utc = NULL;
00258 
00259         utc = osync_time_vtime2utc(vtime, offset);
00260         utime = osync_time_vtime2tm(utc);
00261 
00262         timestamp = osync_time_tm2unix(utime);
00263 
00264         g_free(utc);
00265         g_free(utime);
00266 
00267         osync_trace(TRACE_EXIT, "%s: %lu", __func__, timestamp);
00268         return timestamp;
00269 }
00270 
00276 char *osync_time_unix2vtime(const time_t *timestamp) {
00277 
00278         osync_trace(TRACE_ENTRY, "%s(%lu)", __func__, *timestamp);
00279         char *vtime;
00280         struct tm utc;
00281 
00282         gmtime_r(timestamp, &utc);
00283         vtime = osync_time_tm2vtime(&utc, TRUE);
00284 
00285         osync_trace(TRACE_EXIT, "%s: %s", __func__, vtime);
00286         return vtime;
00287 }
00288 
00294 time_t osync_time_tm2unix(const struct tm *tmtime) {
00295 
00296         time_t timestamp;
00297         struct tm *tmp = g_malloc0(sizeof(struct tm));
00298 
00299         memcpy(tmp, tmtime, sizeof(struct tm));
00300 
00301         timestamp = timegm(tmp);
00302 
00303         g_free(tmp);
00304 
00305         return timestamp; 
00306 }
00307 
00313 struct tm *osync_time_unix2tm(const time_t *timestamp) {
00314 
00315         struct tm *ptr_tm;
00316         struct tm tmtime;
00317         
00318         gmtime_r(timestamp, &tmtime);
00319 
00320         ptr_tm = &tmtime;
00321 
00322         return ptr_tm;
00323 }
00324 
00325 /*
00326  * Timezone helper
00327  */
00328 
00334 int osync_time_timezone_diff(const struct tm *time) {   
00335         osync_trace(TRACE_ENTRY, "%s()", __func__);
00336 
00337         struct tm ltime, utime;
00338         unsigned int lsecs, usecs;
00339         long zonediff;
00340         time_t timestamp;
00341 
00342         timestamp = osync_time_tm2unix(time);
00343 
00344         tzset();
00345 
00346         localtime_r(&timestamp, &ltime);
00347         gmtime_r(&timestamp, &utime);
00348 
00349         lsecs = 3600 * ltime.tm_hour + 60 * ltime.tm_min + ltime.tm_sec;
00350         usecs = 3600 * utime.tm_hour + 60 * utime.tm_min + utime.tm_sec;
00351 
00352         zonediff = lsecs - usecs;
00353 
00354         /* check for different day */
00355         if (utime.tm_mday != ltime.tm_mday) {
00356                 if (utime.tm_mday < ltime.tm_mday)
00357                         zonediff += 24 * 3600; 
00358                 else
00359                         zonediff -= 24 * 3600;
00360         }
00361 
00362         osync_trace(TRACE_EXIT, "%s: %i", __func__, zonediff);
00363         return zonediff;
00364 }
00365 
00373 struct tm *osync_time_tm2utc(const struct tm *ltime, int offset) {
00374 
00375         osync_trace(TRACE_ENTRY, "%s(%p, %i)", __func__, ltime, offset);
00376         struct tm *tmtime = g_malloc0(sizeof(struct tm));
00377 
00378         tmtime->tm_year = ltime->tm_year;
00379         tmtime->tm_mon = ltime->tm_mon;
00380         tmtime->tm_mday = ltime->tm_mday;
00381         tmtime->tm_hour = ltime->tm_hour;
00382         tmtime->tm_min = ltime->tm_min;
00383         tmtime->tm_sec = ltime->tm_sec;
00384 
00385         /* in seconds - to have a exactly timezone diff like -13.5h */
00386         tmtime->tm_hour -= offset / 3600;
00387         tmtime->tm_min -= (offset % 3600) / 60;
00388 
00389         if (tmtime->tm_hour > 23 || tmtime->tm_hour < 0) {
00390         
00391                 if (tmtime->tm_hour < 0) {
00392                         tmtime->tm_hour += 24;
00393                         tmtime->tm_mday -= 1;
00394                 } else {
00395                         tmtime->tm_hour -= 24;
00396                         tmtime->tm_mday += 1;
00397                 }
00398         }
00399 
00400         osync_trace(TRACE_EXIT, "%s: %p", __func__, tmtime);
00401         return tmtime;
00402 }
00403 
00411 struct tm *osync_time_tm2localtime(const struct tm *utime, int offset) {
00412 
00413         struct tm *tmtime = g_malloc0(sizeof(struct tm));
00414         
00415         tmtime->tm_year = utime->tm_year;
00416         tmtime->tm_mon = utime->tm_mon;
00417         tmtime->tm_mday = utime->tm_mday;
00418         tmtime->tm_hour = utime->tm_hour;
00419         tmtime->tm_min = utime->tm_min;
00420         tmtime->tm_sec = utime->tm_sec;
00421 
00422         tmtime->tm_hour += offset / 3600;
00423         tmtime->tm_min += (offset % 3600) / 60;
00424 
00425         if (tmtime->tm_hour > 23 || tmtime->tm_hour < 0) {
00426 
00427                 if (tmtime->tm_hour < 0) {
00428                         tmtime->tm_mday -= 1;
00429                         tmtime->tm_hour += 24;
00430                 } else {
00431                         tmtime->tm_mday += 1;
00432                         tmtime->tm_hour -= 24;
00433                 }
00434         }
00435 
00436         return tmtime; 
00437 }
00438 
00445 char *osync_time_vtime2utc(const char* localtime, int offset) {
00446         osync_trace(TRACE_ENTRY, "%s(%s)", __func__, localtime);
00447         
00448         char *utc = NULL; 
00449         struct tm *tm_local = NULL, *tm_utc = NULL;
00450 
00451         if (strstr(localtime, "Z")) {
00452                 utc = strdup(localtime);
00453                 goto end;
00454         }
00455                 
00456         tm_local = osync_time_vtime2tm(localtime);
00457         tm_utc = osync_time_tm2utc(tm_local, offset);
00458         utc = osync_time_tm2vtime(tm_utc, TRUE);
00459 
00460         g_free(tm_local);
00461 // FIXME is it really a memory leak?
00462 //      g_free(tm_utc);
00463         
00464 end:    
00465         osync_trace(TRACE_EXIT, "%s: %s", __func__, utc);
00466         return utc;
00467 }
00468 
00474 char *osync_time_vtime2localtime(const char* utc, int offset) {
00475         
00476         char *localtime = NULL; 
00477         struct tm *tm_local = NULL, *tm_utc = NULL;
00478 
00479         if (!strstr(utc, "Z")) {
00480                 localtime = strdup(utc);
00481                 return localtime;
00482         }
00483                 
00484         tm_utc = osync_time_vtime2tm(utc);
00485         tm_local = osync_time_tm2localtime(tm_utc, offset);
00486         localtime = osync_time_tm2vtime(tm_local, FALSE);
00487 
00488         g_free(tm_local);
00489         g_free(tm_utc);
00490         
00491         return localtime;
00492 }
00493 
00494 
00495 
00496 /* XXX This functions should only be used as workaround for plugins which
00497    only supports localtime without any timezone information. */
00498 
00502 const char *_time_attr[] = {
00503         "DTSTART:",
00504         "DTEND:",
00505         "DTSTAMP:",
00506         "AALARM:",
00507         "DALARM:",
00508         "DUE:",
00509         NULL
00510 };
00511 
00518 static void _convert_time_field(GString *entry, const char *field, osync_bool toUTC) {
00519 
00520         int i, tzdiff;
00521         char *res = NULL;
00522         char *new_stamp = NULL;
00523 
00524         GString *stamp = g_string_new("");
00525 
00526         if ((res = strstr(entry->str, field))) {
00527                 res += strlen(field);
00528 
00529                 for (i=0; res[i] != '\n' && res[i] != '\r'; i++)
00530                         stamp = g_string_append_c(stamp, res[i]);
00531 
00532                 gssize pos = res - entry->str; 
00533                 entry = g_string_erase(entry, pos, i);
00534 
00535                 // Get System offset to UTC
00536                 struct tm *tm_stamp = osync_time_vtime2tm(stamp->str);
00537                 tzdiff = osync_time_timezone_diff(tm_stamp);
00538                 g_free(tm_stamp);
00539 
00540                 if (toUTC)
00541                         new_stamp = osync_time_vtime2utc(stamp->str, tzdiff);
00542                 else
00543                         new_stamp = osync_time_vtime2localtime(stamp->str, tzdiff); 
00544 
00545                 entry = g_string_insert(entry, pos, new_stamp);
00546                 g_free(new_stamp);
00547         }
00548 }
00549 
00556 char *_convert_entry(const char *vcal, osync_bool toUTC) {
00557 
00558         int i = 0;
00559         GString *new_entry = g_string_new(vcal);
00560 
00561         for (i=0; _time_attr[i] != NULL; i++) 
00562                 _convert_time_field(new_entry, _time_attr[i], toUTC);
00563 
00564         return g_string_free(new_entry, FALSE);
00565 }
00566 
00572 char *osync_time_vcal2localtime(const char *vcal) {
00573 
00574         return _convert_entry(vcal, FALSE);
00575 }
00576 
00582 char *osync_time_vcal2utc(const char *vcal) {
00583 
00584         return _convert_entry(vcal, TRUE);
00585 }
00586 
00593 char *osync_time_sec2alarmdu(int seconds) {
00594 
00595         osync_trace(TRACE_ENTRY, "%s(%i)", __func__, seconds);
00596 
00597         char *tmp = NULL;
00598         char *prefix = NULL;
00599 
00600         if (!seconds) { 
00601                 tmp = g_strdup("PT0S");
00602                 goto end;
00603         }
00604 
00605         if (seconds > 0) { 
00606                 prefix = g_strdup("P");
00607         } else {
00608                 prefix = g_strdup("-P");
00609                 seconds *= -1;
00610         }
00611 
00612         // Days 
00613         if (!(seconds % (3600 * 24))) {
00614                tmp = g_strdup_printf("%s%iD", prefix, seconds / (3600 * 24));
00615                goto end;
00616         }
00617 
00618         // Hours
00619         if (!(seconds % 3600)) {
00620                 tmp = g_strdup_printf("%sT%iH", prefix, seconds / 3600);
00621                 goto end;
00622         }
00623 
00624         // Minutes
00625         if (!(seconds % 60) && seconds < 3600) {
00626                 tmp = g_strdup_printf("%sT%iM", prefix, seconds / 60);
00627                 goto end;
00628         }
00629 
00630         // Seconds
00631         if (seconds < 60) { 
00632                 tmp = g_strdup_printf("%sT%iS", prefix, seconds);
00633                 goto end;
00634         }
00635 
00636         if (seconds > 60)
00637                 tmp = g_strdup_printf("%sT%iM", prefix, seconds / 60);
00638 
00639         if (seconds > 3600)
00640                 tmp = g_strdup_printf("%sT%iH%iM", prefix, seconds / 3600,
00641                                 (seconds % 3600) / 60);
00642 
00643         if (seconds > (3600 * 24))
00644                tmp = g_strdup_printf("%s%iDT%iH%iM", prefix, seconds / (3600 * 24),
00645                                seconds % (3600 * 24) / 3600,
00646                                ((seconds % (3600 * 24) % 3600)) / 60);
00647 
00648 end:
00649         g_free(prefix);
00650 
00651         osync_trace(TRACE_EXIT, "%s: %s", __func__, tmp);
00652         return tmp;
00653 }
00654 
00663 int osync_time_alarmdu2sec(const char *alarm) {
00664 
00665         osync_trace(TRACE_ENTRY, "%s(%s)", __func__, alarm);
00666 
00667         int i, secs, digits;
00668         int is_digit = 0;
00669         int sign = 1;   // when ical stamp doesn't start with '-' => seconds after event
00670         int days = 0, weeks = 0, hours = 0, minutes = 0, seconds = 0;
00671 
00672                 for (i=0; i < (int) strlen(alarm); i++) {
00673 
00674                 switch (alarm[i]) {
00675                         case '-':
00676                                 sign = -1; // seconds before event - change the sign 
00677                         case 'P':
00678                         case 'T':
00679                                 is_digit = 0;
00680                                 break;
00681                         case 'W':
00682                                 is_digit = 0;
00683                                 weeks = digits;
00684                                 break;
00685                         case 'D':
00686                                 is_digit = 0;
00687                                 days = digits;
00688                                 break;
00689                         case 'H':
00690                                 is_digit = 0;
00691                                 hours = digits;
00692                                 break;
00693                         case 'M':
00694                                 is_digit = 0;
00695                                 minutes = digits;
00696                                 break;
00697                         case 'S':
00698                                 is_digit = 0;
00699                                 seconds = digits;
00700                                 break;
00701                         case '0':
00702                         case '1':
00703                         case '2':
00704                         case '3':
00705                         case '4':
00706                         case '5':
00707                         case '6':
00708                         case '7':
00709                         case '8':
00710                         case '9':
00711                                 if (is_digit)
00712                                         break;
00713 
00714                                 sscanf((char*)(alarm+i),"%d",&digits);
00715                                 is_digit = 1;
00716                                 break;
00717                 }
00718         }
00719 
00720         secs = (weeks * 7 * 24 * 3600) + (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
00721 
00722         secs = secs * sign;     // change sign if the alarm is in seconds before event (leading '-')
00723 
00724         osync_trace(TRACE_EXIT, "%s: %i", __func__, secs);
00725         return secs;
00726 }
00727 
00728 /*
00729  * Timezone ID helper
00730  */
00731 
00737 int osync_time_str2wday(const char *swday) {
00738 
00739         int weekday = -1;
00740 
00741         if (!strcmp(swday, "SU"))
00742                 weekday = 0;
00743         else if (!strcmp(swday, "MO"))
00744                 weekday = 1;
00745         else if (!strcmp(swday, "TU"))
00746                 weekday = 2;
00747         else if (!strcmp(swday, "WE"))
00748                 weekday = 3;
00749         else if (!strcmp(swday, "TH"))
00750                 weekday = 4;
00751         else if (!strcmp(swday, "FR"))
00752                 weekday = 5;
00753         else if (!strcmp(swday, "SA"))
00754                 weekday = 6;
00755 
00756         return weekday; 
00757 }
00758 
00769 struct tm *osync_time_relative2tm(const char *byday, const int bymonth, const int year) {
00770 
00771                 struct tm *datestamp = g_malloc0(sizeof(struct tm));
00772                 char weekday[3];
00773                 int first_wday = 0, last_wday = 0;
00774                 int daymod, mday, searched_wday;
00775 
00776                 sscanf(byday, "%d%s", &daymod, weekday); 
00777                 weekday[2] = '\0';
00778 
00779                 searched_wday = osync_time_str2wday(weekday);
00780 
00781                 datestamp->tm_year = year - 1900; 
00782                 datestamp->tm_mon = bymonth - 1;
00783                 datestamp->tm_mday = 0; 
00784                 datestamp->tm_hour = 0; 
00785                 datestamp->tm_min = 0; 
00786                 datestamp->tm_sec = 0;
00787                 datestamp->tm_isdst = -1;
00788 
00789                 for (mday = 0; mday <= 31; mday++) {
00790                         datestamp->tm_mday = mday; 
00791                         mktime(datestamp);
00792 
00793                         if (datestamp->tm_wday == searched_wday) { 
00794                                 if (!first_wday)
00795                                         first_wday = searched_wday;
00796 
00797                                 last_wday = searched_wday;
00798                         }
00799                 }
00800 
00801                 if (daymod > 0)
00802                         datestamp->tm_mday = first_wday + (7 * (daymod - 1));
00803                 else
00804                         datestamp->tm_mday = last_wday - (7 * (daymod - 1));
00805 
00806                 mktime(datestamp);
00807 
00808                 return datestamp;
00809 }
00810 
00816 int osync_time_utcoffset2sec(const char *offset) {
00817         osync_trace(TRACE_ENTRY, "%s(%s)", __func__, offset);
00818 
00819         char csign = 0;
00820         int seconds = 0, sign = 1;
00821         int hours = 0, minutes = 0;
00822 
00823         sscanf(offset, "%c%2d%2d", &csign, &hours, &minutes);
00824 
00825         if (csign == '-')
00826                 sign = -1;
00827 
00828         seconds = (hours * 3600 + minutes * 60) * sign; 
00829 
00830         osync_trace(TRACE_EXIT, "%s: %i", __func__, seconds);
00831         return seconds;
00832 }
00833 
00841 struct tm *osync_time_dstchange(xmlNode *dstNode) {
00842 
00843         int month;
00844         struct tm *dst_change = NULL, *tm_started = NULL;
00845         char *started = NULL, *rule = NULL, *byday = NULL;
00846 
00847         xmlNode *current = osxml_get_node(dstNode, "DateStarted");
00848         started = (char*) xmlNodeGetContent(current);
00849         tm_started = osync_time_vtime2tm(started);
00850         
00851         g_free(started);
00852 
00853         current = osxml_get_node(dstNode, "RecurrenceRule");
00854         current = current->children;
00855 
00856         while (current) {
00857                 rule = (char *) xmlNodeGetContent(current);
00858 
00859                 if (strstr(rule, "BYDAY="))
00860                         byday = g_strdup(rule + 6);
00861                 else if (strstr(rule, "BYMONTH="))
00862                         sscanf(rule, "BYMONTH=%d", &month);
00863                 
00864                 g_free(rule);
00865 
00866                 current = current->next;
00867         }
00868 
00869         dst_change = osync_time_relative2tm(byday, month, tm_started->tm_year + 1900);
00870 
00871         g_free(byday);
00872 
00873         dst_change->tm_hour = tm_started->tm_hour;
00874         dst_change->tm_min = tm_started->tm_min;
00875 
00876         g_free(tm_started);
00877 
00878         return dst_change;
00879 }
00880 
00887 osync_bool osync_time_isdst(const char *vtime, xmlNode *tzid) {
00888 
00889         osync_trace(TRACE_ENTRY, "%s(%s, %p)", __func__, vtime, tzid);
00890 
00891         int year;
00892         char *newyear = NULL;
00893         time_t newyear_t, timestamp;
00894         struct tm *std_changetime, *dst_changetime;
00895         time_t dstStamp, stdStamp;
00896         xmlNode *current = NULL;
00897 
00898         sscanf(vtime, "%4d%*2d%*2dT%*2d%*d%*2d%*c", &year);
00899 
00900         newyear = g_strdup_printf("%4d0101T000000", year);
00901         newyear_t = osync_time_vtime2unix(newyear, 0);
00902         timestamp = osync_time_vtime2unix(vtime, 0);
00903 
00904         /* Handle XML Timezone field */
00905         current = osxml_get_node(tzid, "Standard");
00906         std_changetime = osync_time_dstchange(current);
00907 
00908         current = osxml_get_node(tzid, "DaylightSavings");
00909         dst_changetime = osync_time_dstchange(current);
00910 
00911         /* determine in which timezone is vtime */
00912         dstStamp = osync_time_tm2unix(dst_changetime); 
00913         stdStamp = osync_time_tm2unix(std_changetime);
00914 
00915         if (timestamp > stdStamp && timestamp < dstStamp) {
00916                 osync_trace(TRACE_EXIT, "%s: FALSE (Standard Timezone)", __func__);
00917                 return FALSE;
00918         }       
00919         
00920         osync_trace(TRACE_EXIT, "%s: TRUE (Daylight Saving Timezone)", __func__);
00921         return TRUE; 
00922 }
00923 
00931 int osync_time_tzoffset(const char *vtime, xmlNode *tz) {
00932 
00933         osync_trace(TRACE_ENTRY, "%s(%s, %p)", __func__, vtime, tz);
00934 
00935         int seconds;
00936         char *offset = NULL; 
00937         xmlNode *current = NULL;
00938 
00939         if (osync_time_isdst(vtime, tz))
00940                 current = osxml_get_node(tz, "DaylightSavings");
00941         else
00942                 current = osxml_get_node(tz, "Standard");
00943 
00944         offset = osxml_find_node(current, "TZOffsetFrom");
00945         seconds = osync_time_utcoffset2sec(offset);
00946 
00947         osync_trace(TRACE_EXIT, "%s: %i", __func__, seconds);
00948         return seconds;
00949 }
00950 
00956 char *osync_time_tzid(xmlNode *tz) {
00957         osync_trace(TRACE_ENTRY, "%s(%p)", __func__, tz);
00958 
00959         char *id = NULL; 
00960 
00961         id = osxml_find_node(tz, "TimezoneID");
00962 
00963         osync_trace(TRACE_EXIT, "%s: %s", __func__, id);
00964         return id;
00965 }
00966 
00972 char *osync_time_tzlocation(xmlNode *tz) {
00973         osync_trace(TRACE_ENTRY, "%s(%p)", __func__, tz);
00974 
00975         char *location = NULL; 
00976 
00977         location = osxml_find_node(tz, "TimezoneLocation");
00978 
00979         osync_trace(TRACE_EXIT, "%s: %s", __func__, location);
00980         return location;
00981 }
00982 
00989 xmlNode *osync_time_tzinfo(xmlNode *root, const char *tzid) {
00990         
00991         osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, root, tzid);
00992 
00993         int numnodes, i;
00994         char *tzinfo_tzid = NULL;
00995 
00996         xmlNode *tz = NULL;
00997         xmlNodeSet *nodes = NULL;
00998         xmlXPathObject *xobj = NULL;
00999 
01000         /* search matching Timezone information */
01001         xobj = osxml_get_nodeset(root->doc, "/vcal/Timezone");
01002         nodes = xobj->nodesetval;
01003         numnodes = (nodes) ? nodes->nodeNr : 0;
01004 
01005         osync_trace(TRACE_INTERNAL, "Found %i Timezone field(s)", numnodes);
01006 
01007         if (!numnodes)
01008                 goto noresult;
01009 
01010 
01011         for (i=0; i < numnodes; i++) {
01012                 tz = nodes->nodeTab[i];
01013                 tzinfo_tzid = osync_time_tzid(tz);
01014 
01015                 if (!tzinfo_tzid) {
01016                         g_free(tzinfo_tzid);
01017                         tz = NULL;
01018                         continue;
01019                 }
01020 
01021                 if (!strcmp(tzinfo_tzid, tzid))
01022                         break;
01023         }
01024 
01025         g_free(tzinfo_tzid);
01026 
01027         if (!tz)
01028                 goto noresult;
01029                 
01030 
01031         osync_trace(TRACE_EXIT, "%s: %p", __func__, tz);
01032         return tz;
01033 
01034 noresult:       
01035         osync_trace(TRACE_EXIT, "%s: No matching Timezone node found. Seems to be a be a floating timestamp.", __func__);
01036         return NULL;
01037 }
01038 
01045 char *osync_time_tzlocal2utc(xmlNode *root, const char *field) {
01046         osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, root, field);
01047 
01048         int offset = 0;
01049         char *utc = NULL, *field_tzid = NULL, *vtime = NULL;
01050         xmlNode *tz = NULL;
01051 
01052         /*
01053         node = osxml_get_node(root, field);
01054         if (!node) {
01055                 osync_trace(TRACE_EXIT, "%s: field \"%s\" not found", __func__, field);
01056                 return NULL;
01057         }
01058         */
01059 
01060         field_tzid = osync_time_tzid(root);
01061         if (!field_tzid) {
01062                 g_free(field_tzid);
01063                 goto noresult;
01064         }
01065 
01066         tz = osync_time_tzinfo(root, field_tzid);
01067         g_free(field_tzid);
01068 
01069         if (!tz)
01070                 goto noresult;
01071 
01072         vtime = osxml_find_node(root, "Content");
01073 
01074         /* Handle UTC offset like 13.5h */
01075         offset = osync_time_tzoffset(vtime, tz);
01076         struct tm *ttm = osync_time_vtime2tm(vtime);
01077         ttm->tm_hour -= offset / 3600;
01078         ttm->tm_min -= (offset % 3600) / 60;
01079         mktime(ttm);
01080         utc = osync_time_tm2vtime(ttm, TRUE);
01081 
01082         g_free(vtime);
01083         g_free(ttm);
01084 
01085         osync_trace(TRACE_EXIT, "%s: %s", __func__, utc);
01086         return utc;
01087 
01088 noresult:
01089         osync_trace(TRACE_EXIT, "%s: No matching Timezone node is found.", __func__);   
01090         return NULL;
01091 }
01092 

Generated on Mon Jul 26 2010 for OpenSync by  doxygen 1.7.1