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(getenv("TZ") != 0){
98 orig_tzid = (char*)icalmemory_strdup(getenv("TZ"));
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)
167 memset(&stm,0,sizeof( struct tm));
169 if(icaltime_is_null_time(tt)) {
173 stm.tm_sec = tt.second;
174 stm.tm_min = tt.minute;
175 stm.tm_hour = tt.hour;
176 stm.tm_mday = tt.day;
177 stm.tm_mon = tt.month-1;
178 stm.tm_year = tt.year-1900;
181 if(tt.is_utc == 1 && tt.is_date == 0){
182 struct set_tz_save old_tz = set_tz("UTC");
193 char* icaltime_as_ical_string(struct icaltimetype tt)
196 char* buf = icalmemory_new_buffer(size);
199 snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day);
203 fmt = "%04d%02d%02dT%02d%02d%02dZ";
205 fmt = "%04d%02d%02dT%02d%02d%02d";
207 snprintf(buf, size,fmt,tt.year,tt.month,tt.day,
208 tt.hour,tt.minute,tt.second);
211 icalmemory_add_tmp_buffer(buf);
218 /* convert tt, of timezone tzid, into a utc time */
219 struct icaltimetype icaltime_as_utc(struct icaltimetype tt,const char* tzid)
223 if(tt.is_utc == 1 || tt.is_date == 1){
227 tzid_offset = icaltime_utc_offset(tt,tzid);
229 tt.second -= tzid_offset;
233 return icaltime_normalize(tt);
236 /* convert tt, a time in UTC, into a time in timezone tzid */
237 struct icaltimetype icaltime_as_zone(struct icaltimetype tt,const char* tzid)
241 tzid_offset = icaltime_utc_offset(tt,tzid);
243 tt.second += tzid_offset;
247 return icaltime_normalize(tt);
252 /* Return the offset of the named zone as seconds. tt is a time
253 indicating the date for which you want the offset */
254 int icaltime_utc_offset(struct icaltimetype ictt, const char* tzid)
257 time_t tt = icaltime_as_timet(ictt);
259 struct tm gtm, buft1, buft2;
260 struct set_tz_save old_tz;
263 old_tz = set_tz(tzid);
266 /* Mis-interpret a UTC broken out time as local time */
267 gtm = *(gmtime_r(&tt, &buft1));
268 gtm.tm_isdst = localtime_r(&tt, &buft2)->tm_isdst;
269 offset_tt = mktime(>m);
280 /* Normalize by converting from localtime to utc and back to local
281 time. This uses localtime because localtime and mktime are inverses
284 struct icaltimetype icaltime_normalize(struct icaltimetype tt)
289 memset(&stm,0,sizeof( struct tm));
291 stm.tm_sec = tt.second;
292 stm.tm_min = tt.minute;
293 stm.tm_hour = tt.hour;
294 stm.tm_mday = tt.day;
295 stm.tm_mon = tt.month-1;
296 stm.tm_year = tt.year-1900;
297 stm.tm_isdst = -1; /* prevents mktime from changing hour based on
302 stm = *(localtime_r(&tut, &buft));
304 tt.second = stm.tm_sec;
305 tt.minute = stm.tm_min;
306 tt.hour = stm.tm_hour;
307 tt.day = stm.tm_mday;
308 tt.month = stm.tm_mon +1;
309 tt.year = stm.tm_year+1900;
315 #ifndef ICAL_NO_LIBICAL
316 #include "icalvalue.h"
318 struct icaltimetype icaltime_from_string(const char* str)
320 struct icaltimetype tt = icaltime_null_time();
323 icalerror_check_arg_re(str!=0,"str",icaltime_null_time());
327 if(size == 15) { /* floating time */
330 } else if (size == 16) { /* UTC time, ends in 'Z'*/
335 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
336 return icaltime_null_time();
339 } else if (size == 8) { /* A DATE */
342 } else if (size == 20) { /* A shitty date by Outlook */
343 char tsep, offset_way;
345 sscanf(str,"%04d%02d%02d%c%02d%02d%02d%c%02d%02d",&tt.year,&tt.month,&tt.day,
346 &tsep,&tt.hour,&tt.minute,&tt.second, &offset_way, &off_h, &off_m);
349 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
350 return icaltime_null_time();
352 if (offset_way != '-' && offset_way != '+'){
353 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
354 return icaltime_null_time();
357 /* substract offset to get utc */
358 if (offset_way == '-')
359 tt.second += 3600*off_h;
361 tt.second -= 3600*off_h;
364 return icaltime_normalize(tt);
366 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
367 return icaltime_null_time();
371 sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day);
374 sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day,
375 &tsep,&tt.hour,&tt.minute,&tt.second);
378 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
379 return icaltime_null_time();
389 char* icaltime_as_ctime(struct icaltimetype t)
393 tt = icaltime_as_timet(t);
394 sprintf(ctime_str,"%s",ctime_r(&tt, buft));
396 ctime_str[strlen(ctime_str)-1] = 0;
402 short days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
404 short icaltime_days_in_month(short month,short year)
408 int days = days_in_month[month];
413 if( (year % 4 == 0 && year % 100 != 0) ||
425 /* 1-> Sunday, 7->Saturday */
426 short icaltime_day_of_week(struct icaltimetype t){
428 time_t tt = icaltime_as_timet(t);
432 tm = gmtime_r(&tt, &buft);
434 tm = localtime_r(&tt, &buft);
437 return tm->tm_wday+1;
440 /* Day of the year that the first day of the week (Sunday) is on */
441 short icaltime_start_doy_of_week(struct icaltimetype t){
442 time_t tt = icaltime_as_timet(t);
444 struct tm *stm, buft1, buft2;
447 stm = gmtime_r(&tt, &buft1);
448 syear = stm->tm_year;
450 start_tt = tt - stm->tm_wday*(60*60*24);
452 stm = gmtime_r(&start_tt, &buft2);
454 if(syear == stm->tm_year){
455 return stm->tm_yday+1;
457 /* return negative to indicate that start of week is in
460 int year = stm->tm_year;
462 if( (year % 4 == 0 && year % 100 != 0) ||
467 return (stm->tm_yday+1)-(365+is_leap);
472 short icaltime_week_number(struct icaltimetype ictt)
475 time_t t = icaltime_as_timet(ictt);
479 strftime(str,5,"%V", gmtime_r(&t, &buft));
488 short icaltime_day_of_year(struct icaltimetype t){
489 time_t tt = icaltime_as_timet(t);
490 struct tm *stm, buft;
493 stm = gmtime_r(&tt, &buft);
495 stm = localtime_r(&tt, &buft);
498 return stm->tm_yday+1;
502 /* Jan 1 is day #1, not 0 */
503 struct icaltimetype icaltime_from_day_of_year(short doy, short year)
507 struct set_tz_save old_tz = set_tz("UTC");
509 /* Get the time of january 1 of this year*/
510 memset(&stm,0,sizeof(struct tm));
511 stm.tm_year = year-1900;
518 /* Now add in the days */
523 return icaltime_from_timet(tt, 1);
526 struct icaltimetype icaltime_null_time()
528 struct icaltimetype t;
529 memset(&t,0,sizeof(struct icaltimetype));
535 int icaltime_is_valid_time(struct icaltimetype t){
536 if(t.is_utc > 1 || t.is_utc < 0 ||
537 t.year < 0 || t.year > 3000 ||
538 t.is_date > 1 || t.is_date < 0){
546 int icaltime_is_null_time(struct icaltimetype t)
548 if (t.second +t.minute+t.hour+t.day+t.month+t.year == 0){
556 int icaltime_compare(struct icaltimetype a,struct icaltimetype b)
558 time_t t1 = icaltime_as_timet(a);
559 time_t t2 = icaltime_as_timet(b);
563 } else if (t1 < t2) {
572 icaltime_compare_date_only (struct icaltimetype a, struct icaltimetype b)
577 if (a.year == b.year && a.month == b.month && a.day == b.day)
580 t1 = icaltime_as_timet (a);
581 t2 = icaltime_as_timet (b);
595 /* These are defined in icalduration.c:
596 struct icaltimetype icaltime_add(struct icaltimetype t,
597 struct icaldurationtype d)
598 struct icaldurationtype icaltime_subtract(struct icaltimetype t1,
599 struct icaltimetype t2)