2 ======================================================================
4 CREATOR: eric 02 June 2000
9 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of either:
14 The LGPL as published by the Free Software Foundation, version
15 2.1, available at: http://www.fsf.org/copyleft/lesser.html
19 The Mozilla Public License Version 1.0. You may obtain a copy of
20 the License at http://www.mozilla.org/MPL/
22 The Original Code is eric. The Initial Developer of the Original
26 ======================================================================*/
43 #ifdef ICAL_NO_LIBICAL
44 #define icalerror_set_errno(x)
45 #define icalerror_check_arg_rv(x,y)
46 #define icalerror_check_arg_re(x,y,z)
48 #include "icalerror.h"
49 #include "icalmemory.h"
56 icaltime_from_timet(time_t tm, int is_date)
58 struct icaltimetype tt = icaltime_null_time();
61 t = *(gmtime_r(&tm, &buft));
68 tt.second = tt.minute =tt.hour = 0 ;
72 tt.month = t.tm_mon + 1;
73 tt.year = t.tm_year+ 1900;
81 /* Structure used by set_tz to hold an old value of TZ, and the new
82 value, which is in memory we will have to free in unset_tz */
83 struct set_tz_save {char* orig_tzid; char* new_env_str;};
85 /* Temporarily change the TZ environmental variable. */
86 struct set_tz_save set_tz(const char* tzid)
91 struct set_tz_save savetz;
95 savetz.new_env_str = 0;
97 if (g_getenv("TZ") != NULL) {
98 orig_tzid = (char*)icalmemory_strdup(g_getenv("TZ"));
100 if (orig_tzid == 0) {
101 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
106 tmp_sz =strlen(tzid)+4;
107 new_env_str = (char*)malloc(tmp_sz);
109 if(new_env_str == 0){
110 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
115 /* Copy the TZid into a string with the form that putenv expects. */
116 strcpy(new_env_str,"TZ=");
117 strcpy(new_env_str+3,tzid);
121 /* Old value of TZ and the string we will have to free later */
122 savetz.orig_tzid = orig_tzid;
123 savetz.new_env_str = new_env_str;
130 void unset_tz(struct set_tz_save savetz)
132 /* restore the original TZ environment */
134 char* orig_tzid = savetz.orig_tzid;
137 size_t tmp_sz =strlen(orig_tzid)+4;
138 char* orig_env_str = (char*)malloc(tmp_sz);
140 if(orig_env_str == 0){
141 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
145 strcpy(orig_env_str,"TZ=");
146 strcpy(orig_env_str+3,orig_tzid);
148 putenv(orig_env_str);
152 g_unsetenv("TZ"); /* Delete from environment */
155 if(savetz.new_env_str != 0){
156 free(savetz.new_env_str);
162 time_t icaltime_as_timet(struct icaltimetype tt)
171 zone = g_time_zone_new_utc();
173 zone = g_time_zone_new_local();
175 dt = g_date_time_new(
184 /* Got to return something... */
188 t = g_date_time_to_unix(dt);
190 g_date_time_unref(dt);
191 g_time_zone_unref(zone);
196 memset(&stm,0,sizeof( struct tm));
198 if(icaltime_is_null_time(tt)) {
202 stm.tm_sec = tt.second;
203 stm.tm_min = tt.minute;
204 stm.tm_hour = tt.hour;
205 stm.tm_mday = tt.day;
206 stm.tm_mon = tt.month-1;
207 stm.tm_year = tt.year-1900;
210 if(tt.is_utc == 1 && tt.is_date == 0){
211 struct set_tz_save old_tz = set_tz("UTC");
222 char* icaltime_as_ical_string(struct icaltimetype tt)
225 char* buf = icalmemory_new_buffer(size);
228 snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day);
232 fmt = "%04d%02d%02dT%02d%02d%02dZ";
234 fmt = "%04d%02d%02dT%02d%02d%02d";
236 snprintf(buf, size,fmt,tt.year,tt.month,tt.day,
237 tt.hour,tt.minute,tt.second);
240 icalmemory_add_tmp_buffer(buf);
247 /* convert tt, of timezone tzid, into a utc time */
248 struct icaltimetype icaltime_as_utc(struct icaltimetype tt,const char* tzid)
252 if(tt.is_utc == 1 || tt.is_date == 1){
256 tzid_offset = icaltime_utc_offset(tt,tzid);
258 tt.second -= tzid_offset;
262 return icaltime_normalize(tt);
265 /* convert tt, a time in UTC, into a time in timezone tzid */
266 struct icaltimetype icaltime_as_zone(struct icaltimetype tt,const char* tzid)
270 tzid_offset = icaltime_utc_offset(tt,tzid);
272 tt.second += tzid_offset;
276 return icaltime_normalize(tt);
281 /* Return the offset of the named zone as seconds. tt is a time
282 indicating the date for which you want the offset */
283 int icaltime_utc_offset(struct icaltimetype ictt, const char* tzid)
286 time_t tt = icaltime_as_timet(ictt);
288 struct tm gtm, buft1, buft2;
289 struct set_tz_save old_tz;
292 old_tz = set_tz(tzid);
295 /* Mis-interpret a UTC broken out time as local time */
296 gtm = *(gmtime_r(&tt, &buft1));
297 gtm.tm_isdst = localtime_r(&tt, &buft2)->tm_isdst;
298 offset_tt = mktime(>m);
309 /* Normalize by converting from localtime to utc and back to local
310 time. This uses localtime because localtime and mktime are inverses
313 struct icaltimetype icaltime_normalize(struct icaltimetype tt)
319 memset(&stm,0,sizeof( struct tm));
321 stm.tm_sec = tt.second;
322 stm.tm_min = tt.minute;
323 stm.tm_hour = tt.hour;
324 stm.tm_mday = tt.day;
325 stm.tm_mon = tt.month-1;
326 stm.tm_year = tt.year-1900;
327 stm.tm_isdst = -1; /* prevents mktime from changing hour based on
332 stm = *(localtime_r(&tut, &buft));
334 tt.second = stm.tm_sec;
335 tt.minute = stm.tm_min;
336 tt.hour = stm.tm_hour;
337 tt.day = stm.tm_mday;
338 tt.month = stm.tm_mon +1;
339 tt.year = stm.tm_year+1900;
345 #ifndef ICAL_NO_LIBICAL
346 #include "icalvalue.h"
348 struct icaltimetype icaltime_from_string(const char* str)
350 struct icaltimetype tt = icaltime_null_time();
353 icalerror_check_arg_re(str!=0,"str",icaltime_null_time());
357 if(size == 15) { /* floating time */
360 } else if (size == 16) { /* UTC time, ends in 'Z'*/
365 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
366 return icaltime_null_time();
369 } else if (size == 8) { /* A DATE */
372 } else if (size == 20) { /* A shitty date by Outlook */
373 char tsep, offset_way;
375 sscanf(str,"%04d%02d%02d%c%02d%02d%02d%c%02d%02d",&tt.year,&tt.month,&tt.day,
376 &tsep,&tt.hour,&tt.minute,&tt.second, &offset_way, &off_h, &off_m);
379 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
380 return icaltime_null_time();
382 if (offset_way != '-' && offset_way != '+'){
383 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
384 return icaltime_null_time();
387 /* substract offset to get utc */
388 if (offset_way == '-')
389 tt.second += 3600*off_h;
391 tt.second -= 3600*off_h;
394 return icaltime_normalize(tt);
396 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
397 return icaltime_null_time();
401 sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day);
404 sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day,
405 &tsep,&tt.hour,&tt.minute,&tt.second);
408 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
409 return icaltime_null_time();
419 char* icaltime_as_ctime(struct icaltimetype t)
423 tt = icaltime_as_timet(t);
424 sprintf(ctime_str,"%s",ctime_r(&tt, buft));
426 ctime_str[strlen(ctime_str)-1] = 0;
432 short days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
434 short icaltime_days_in_month(short month,short year)
438 int days = days_in_month[month];
443 if( (year % 4 == 0 && year % 100 != 0) ||
455 /* 1-> Sunday, 7->Saturday */
456 short icaltime_day_of_week(struct icaltimetype t){
458 time_t tt = icaltime_as_timet(t);
462 tm = gmtime_r(&tt, &buft);
464 tm = localtime_r(&tt, &buft);
467 return tm->tm_wday+1;
470 /* Day of the year that the first day of the week (Sunday) is on */
471 short icaltime_start_doy_of_week(struct icaltimetype t){
472 time_t tt = icaltime_as_timet(t);
474 struct tm *stm, buft1, buft2;
477 stm = gmtime_r(&tt, &buft1);
478 syear = stm->tm_year;
480 start_tt = tt - stm->tm_wday*(60*60*24);
482 stm = gmtime_r(&start_tt, &buft2);
484 if(syear == stm->tm_year){
485 return stm->tm_yday+1;
487 /* return negative to indicate that start of week is in
490 int year = stm->tm_year;
492 if( (year % 4 == 0 && year % 100 != 0) ||
497 return (stm->tm_yday+1)-(365+is_leap);
502 short icaltime_week_number(struct icaltimetype ictt)
505 time_t t = icaltime_as_timet(ictt);
509 strftime(str,5,"%V", gmtime_r(&t, &buft));
518 short icaltime_day_of_year(struct icaltimetype t){
524 zone = g_time_zone_new_utc();
526 zone = g_time_zone_new_local();
528 dt = g_date_time_new(
537 /* Got to return something... */
541 gint doy = g_date_time_get_day_of_year(dt);
542 g_date_time_unref(dt);
543 g_time_zone_unref(zone);
548 time_t tt = icaltime_as_timet(t);
549 struct tm *stm, buft;
552 stm = gmtime_r(&tt, &buft);
554 stm = localtime_r(&tt, &buft);
557 return stm->tm_yday+1;
561 /* Jan 1 is day #1, not 0 */
562 struct icaltimetype icaltime_from_day_of_year(short doy, short year)
565 GDateTime *dt = g_date_time_new_utc(
572 GDateTime *dtd = g_date_time_add_days(dt, doy);
574 g_date_time_unref(dt);
575 struct icaltimetype t = icaltime_null_time();
577 t.year = g_date_time_get_year(dtd);
578 t.month = g_date_time_get_month(dtd);
579 t.day = g_date_time_get_day_of_month(dtd);
580 t.hour = g_date_time_get_hour(dtd);
581 t.minute = g_date_time_get_minute(dtd);
582 t.second = g_date_time_get_second(dtd);
585 g_date_time_unref(dtd);
592 struct set_tz_save old_tz = set_tz("UTC");
594 /* Get the time of january 1 of this year*/
595 memset(&stm,0,sizeof(struct tm));
596 stm.tm_year = year-1900;
603 /* Now add in the days */
608 return icaltime_from_timet(tt, 1);
612 struct icaltimetype icaltime_null_time()
614 struct icaltimetype t;
615 memset(&t,0,sizeof(struct icaltimetype));
621 int icaltime_is_valid_time(struct icaltimetype t){
622 if(t.is_utc > 1 || t.is_utc < 0 ||
623 t.year < 0 || t.year > 3000 ||
624 t.is_date > 1 || t.is_date < 0){
632 int icaltime_is_null_time(struct icaltimetype t)
634 if (t.second +t.minute+t.hour+t.day+t.month+t.year == 0){
642 int icaltime_compare(struct icaltimetype a,struct icaltimetype b)
644 time_t t1 = icaltime_as_timet(a);
645 time_t t2 = icaltime_as_timet(b);
649 } else if (t1 < t2) {
658 icaltime_compare_date_only (struct icaltimetype a, struct icaltimetype b)
663 if (a.year == b.year && a.month == b.month && a.day == b.day)
666 t1 = icaltime_as_timet (a);
667 t2 = icaltime_as_timet (b);
681 /* These are defined in icalduration.c:
682 struct icaltimetype icaltime_add(struct icaltimetype t,
683 struct icaldurationtype d)
684 struct icaldurationtype icaltime_subtract(struct icaltimetype t1,
685 struct icaltimetype t2)