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);
114 /* Copy the TZid into a string with the form that putenv expects. */
115 strcpy(new_env_str,"TZ=");
116 strcpy(new_env_str+3,tzid);
120 /* Old value of TZ and the string we will have to free later */
121 savetz.orig_tzid = orig_tzid;
122 savetz.new_env_str = new_env_str;
129 void unset_tz(struct set_tz_save savetz)
131 /* restore the original TZ environment */
133 char* orig_tzid = savetz.orig_tzid;
136 size_t tmp_sz =strlen(orig_tzid)+4;
137 char* orig_env_str = (char*)malloc(tmp_sz);
139 if(orig_env_str == 0){
140 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
144 strcpy(orig_env_str,"TZ=");
145 strcpy(orig_env_str+3,orig_tzid);
147 putenv(orig_env_str);
151 g_unsetenv("TZ"); /* Delete from environment */
154 if(savetz.new_env_str != 0){
155 free(savetz.new_env_str);
161 time_t icaltime_as_timet(struct icaltimetype tt)
166 memset(&stm,0,sizeof( struct tm));
168 if(icaltime_is_null_time(tt)) {
172 stm.tm_sec = tt.second;
173 stm.tm_min = tt.minute;
174 stm.tm_hour = tt.hour;
175 stm.tm_mday = tt.day;
176 stm.tm_mon = tt.month-1;
177 stm.tm_year = tt.year-1900;
180 if(tt.is_utc == 1 && tt.is_date == 0){
181 struct set_tz_save old_tz = set_tz("UTC");
192 char* icaltime_as_ical_string(struct icaltimetype tt)
195 char* buf = icalmemory_new_buffer(size);
198 snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day);
202 fmt = "%04d%02d%02dT%02d%02d%02dZ";
204 fmt = "%04d%02d%02dT%02d%02d%02d";
206 snprintf(buf, size,fmt,tt.year,tt.month,tt.day,
207 tt.hour,tt.minute,tt.second);
210 icalmemory_add_tmp_buffer(buf);
217 /* convert tt, of timezone tzid, into a utc time */
218 struct icaltimetype icaltime_as_utc(struct icaltimetype tt,const char* tzid)
222 if(tt.is_utc == 1 || tt.is_date == 1){
226 tzid_offset = icaltime_utc_offset(tt,tzid);
228 tt.second -= tzid_offset;
232 return icaltime_normalize(tt);
235 /* convert tt, a time in UTC, into a time in timezone tzid */
236 struct icaltimetype icaltime_as_zone(struct icaltimetype tt,const char* tzid)
240 tzid_offset = icaltime_utc_offset(tt,tzid);
242 tt.second += tzid_offset;
246 return icaltime_normalize(tt);
251 /* Return the offset of the named zone as seconds. tt is a time
252 indicating the date for which you want the offset */
253 int icaltime_utc_offset(struct icaltimetype ictt, const char* tzid)
256 time_t tt = icaltime_as_timet(ictt);
258 struct tm gtm, buft1, buft2;
259 struct set_tz_save old_tz;
262 old_tz = set_tz(tzid);
265 /* Mis-interpret a UTC broken out time as local time */
266 gtm = *(gmtime_r(&tt, &buft1));
267 gtm.tm_isdst = localtime_r(&tt, &buft2)->tm_isdst;
268 offset_tt = mktime(>m);
279 /* Normalize by converting from localtime to utc and back to local
280 time. This uses localtime because localtime and mktime are inverses
283 struct icaltimetype icaltime_normalize(struct icaltimetype tt)
288 memset(&stm,0,sizeof( struct tm));
290 stm.tm_sec = tt.second;
291 stm.tm_min = tt.minute;
292 stm.tm_hour = tt.hour;
293 stm.tm_mday = tt.day;
294 stm.tm_mon = tt.month-1;
295 stm.tm_year = tt.year-1900;
296 stm.tm_isdst = -1; /* prevents mktime from changing hour based on
301 stm = *(localtime_r(&tut, &buft));
303 tt.second = stm.tm_sec;
304 tt.minute = stm.tm_min;
305 tt.hour = stm.tm_hour;
306 tt.day = stm.tm_mday;
307 tt.month = stm.tm_mon +1;
308 tt.year = stm.tm_year+1900;
314 #ifndef ICAL_NO_LIBICAL
315 #include "icalvalue.h"
317 struct icaltimetype icaltime_from_string(const char* str)
319 struct icaltimetype tt = icaltime_null_time();
322 icalerror_check_arg_re(str!=0,"str",icaltime_null_time());
326 if(size == 15) { /* floating time */
329 } else if (size == 16) { /* UTC time, ends in 'Z'*/
334 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
335 return icaltime_null_time();
338 } else if (size == 8) { /* A DATE */
341 } else if (size == 20) { /* A shitty date by Outlook */
342 char tsep, offset_way;
344 sscanf(str,"%04d%02d%02d%c%02d%02d%02d%c%02d%02d",&tt.year,&tt.month,&tt.day,
345 &tsep,&tt.hour,&tt.minute,&tt.second, &offset_way, &off_h, &off_m);
348 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
349 return icaltime_null_time();
351 if (offset_way != '-' && offset_way != '+'){
352 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
353 return icaltime_null_time();
356 /* substract offset to get utc */
357 if (offset_way == '-')
358 tt.second += 3600*off_h;
360 tt.second -= 3600*off_h;
363 return icaltime_normalize(tt);
365 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
366 return icaltime_null_time();
370 sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day);
373 sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day,
374 &tsep,&tt.hour,&tt.minute,&tt.second);
377 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
378 return icaltime_null_time();
388 char* icaltime_as_ctime(struct icaltimetype t)
392 tt = icaltime_as_timet(t);
393 sprintf(ctime_str,"%s",ctime_r(&tt, buft));
395 ctime_str[strlen(ctime_str)-1] = 0;
401 short days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
403 short icaltime_days_in_month(short month,short year)
407 int days = days_in_month[month];
412 if( (year % 4 == 0 && year % 100 != 0) ||
424 /* 1-> Sunday, 7->Saturday */
425 short icaltime_day_of_week(struct icaltimetype t){
427 time_t tt = icaltime_as_timet(t);
431 tm = gmtime_r(&tt, &buft);
433 tm = localtime_r(&tt, &buft);
436 return tm->tm_wday+1;
439 /* Day of the year that the first day of the week (Sunday) is on */
440 short icaltime_start_doy_of_week(struct icaltimetype t){
441 time_t tt = icaltime_as_timet(t);
443 struct tm *stm, buft1, buft2;
446 stm = gmtime_r(&tt, &buft1);
447 syear = stm->tm_year;
449 start_tt = tt - stm->tm_wday*(60*60*24);
451 stm = gmtime_r(&start_tt, &buft2);
453 if(syear == stm->tm_year){
454 return stm->tm_yday+1;
456 /* return negative to indicate that start of week is in
459 int year = stm->tm_year;
461 if( (year % 4 == 0 && year % 100 != 0) ||
466 return (stm->tm_yday+1)-(365+is_leap);
471 short icaltime_week_number(struct icaltimetype ictt)
474 time_t t = icaltime_as_timet(ictt);
478 strftime(str,5,"%V", gmtime_r(&t, &buft));
487 short icaltime_day_of_year(struct icaltimetype t){
488 time_t tt = icaltime_as_timet(t);
489 struct tm *stm, buft;
492 stm = gmtime_r(&tt, &buft);
494 stm = localtime_r(&tt, &buft);
497 return stm->tm_yday+1;
501 /* Jan 1 is day #1, not 0 */
502 struct icaltimetype icaltime_from_day_of_year(short doy, short year)
506 struct set_tz_save old_tz = set_tz("UTC");
508 /* Get the time of january 1 of this year*/
509 memset(&stm,0,sizeof(struct tm));
510 stm.tm_year = year-1900;
517 /* Now add in the days */
522 return icaltime_from_timet(tt, 1);
525 struct icaltimetype icaltime_null_time()
527 struct icaltimetype t;
528 memset(&t,0,sizeof(struct icaltimetype));
534 int icaltime_is_valid_time(struct icaltimetype t){
535 if(t.is_utc > 1 || t.is_utc < 0 ||
536 t.year < 0 || t.year > 3000 ||
537 t.is_date > 1 || t.is_date < 0){
545 int icaltime_is_null_time(struct icaltimetype t)
547 if (t.second +t.minute+t.hour+t.day+t.month+t.year == 0){
555 int icaltime_compare(struct icaltimetype a,struct icaltimetype b)
557 time_t t1 = icaltime_as_timet(a);
558 time_t t2 = icaltime_as_timet(b);
562 } else if (t1 < t2) {
571 icaltime_compare_date_only (struct icaltimetype a, struct icaltimetype b)
576 if (a.year == b.year && a.month == b.month && a.day == b.day)
579 t1 = icaltime_as_timet (a);
580 t2 = icaltime_as_timet (b);
594 /* These are defined in icalduration.c:
595 struct icaltimetype icaltime_add(struct icaltimetype t,
596 struct icaldurationtype d)
597 struct icaldurationtype icaltime_subtract(struct icaltimetype t1,
598 struct icaltimetype t2)