summaryrefslogtreecommitdiffabout
path: root/libical/src/libical/icaltime.c
authorzautrix <zautrix>2004-06-26 19:01:18 (UTC)
committer zautrix <zautrix>2004-06-26 19:01:18 (UTC)
commitb9aad1f15dc600e4dbe4c62d3fcced6363188ba3 (patch) (unidiff)
tree2c3d4004fb21c72cba65793859f9bcd8ffd3a49c /libical/src/libical/icaltime.c
downloadkdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.zip
kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.gz
kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.bz2
Initial revision
Diffstat (limited to 'libical/src/libical/icaltime.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libical/src/libical/icaltime.c577
1 files changed, 577 insertions, 0 deletions
diff --git a/libical/src/libical/icaltime.c b/libical/src/libical/icaltime.c
new file mode 100644
index 0000000..a04ca04
--- a/dev/null
+++ b/libical/src/libical/icaltime.c
@@ -0,0 +1,577 @@
1/* -*- Mode: C -*-
2 ======================================================================
3 FILE: icaltime.c
4 CREATOR: eric 02 June 2000
5
6 $Id$
7 $Locker$
8
9 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of either:
13
14 The LGPL as published by the Free Software Foundation, version
15 2.1, available at: http://www.fsf.org/copyleft/lesser.html
16
17 Or:
18
19 The Mozilla Public License Version 1.0. You may obtain a copy of
20 the License at http://www.mozilla.org/MPL/
21
22 The Original Code is eric. The Initial Developer of the Original
23 Code is Eric Busboom
24
25
26 ======================================================================*/
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32#include "icaltime.h"
33#include <assert.h>
34#include <string.h>
35#include <stdlib.h>
36#include <stdio.h>
37
38int snprintf(char *str, size_t n, char const *fmt, ...);
39
40#ifdef ICAL_NO_LIBICAL
41#define icalerror_set_errno(x)
42#define icalerror_check_arg_rv(x,y)
43#define icalerror_check_arg_re(x,y,z)
44#else
45#include "icalerror.h"
46#include "icalmemory.h"
47#endif
48
49
50
51
52struct icaltimetype
53icaltime_from_timet(time_t tm, int is_date)
54{
55 struct icaltimetype tt = icaltime_null_time();
56 struct tm t;
57
58 t = *(gmtime(&tm));
59
60 if(is_date == 0){
61 tt.second = t.tm_sec;
62 tt.minute = t.tm_min;
63 tt.hour = t.tm_hour;
64 } else {
65 tt.second = tt.minute =tt.hour = 0 ;
66 }
67
68 tt.day = t.tm_mday;
69 tt.month = t.tm_mon + 1;
70 tt.year = t.tm_year+ 1900;
71
72 tt.is_utc = 1;
73 tt.is_date = is_date;
74
75 return tt;
76}
77
78/* Structure used by set_tz to hold an old value of TZ, and the new
79 value, which is in memory we will have to free in unset_tz */
80struct set_tz_save {char* orig_tzid; char* new_env_str;};
81
82/* Temporarily change the TZ environmental variable. */
83struct set_tz_save set_tz(const char* tzid)
84{
85
86 char *orig_tzid = 0;
87 char *new_env_str;
88 struct set_tz_save savetz;
89 size_t tmp_sz;
90
91 savetz.orig_tzid = 0;
92 savetz.new_env_str = 0;
93
94 if(getenv("TZ") != 0){
95 orig_tzid = (char*)icalmemory_strdup(getenv("TZ"));
96
97 if(orig_tzid == 0){
98 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
99 return savetz;
100 }
101 }
102
103 tmp_sz =strlen(tzid)+4;
104 new_env_str = (char*)malloc(tmp_sz);
105
106 if(new_env_str == 0){
107 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
108 return savetz;
109 }
110
111 /* Copy the TZid into a string with the form that putenv expects. */
112 strcpy(new_env_str,"TZ=");
113 strcpy(new_env_str+3,tzid);
114
115 putenv(new_env_str);
116
117 /* Old value of TZ and the string we will have to free later */
118 savetz.orig_tzid = orig_tzid;
119 savetz.new_env_str = new_env_str;
120 return savetz;
121}
122
123void unset_tz(struct set_tz_save savetz)
124{
125 /* restore the original TZ environment */
126
127 char* orig_tzid = savetz.orig_tzid;
128
129 if(orig_tzid!=0){
130 size_t tmp_sz =strlen(orig_tzid)+4;
131 char* orig_env_str = (char*)icalmemory_tmp_buffer(tmp_sz);
132
133 if(orig_env_str == 0){
134 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
135 return;
136 }
137
138 strcpy(orig_env_str,"TZ=");
139 strcpy(orig_env_str+3,orig_tzid);
140#ifndef _WIN32
141 setenv("TZ", savetz.orig_tzid,1 );
142#else
143 putenv("TZ=MEZ");//, savetz.orig_tzid );
144#endif
145 free(orig_tzid);
146 } else {
147#ifdef __FreeBSD__
148 unsetenv("TZ");
149#else
150 putenv("TZ"); /* Delete from environment */
151#endif
152 }
153
154 if(savetz.new_env_str != 0){
155 free(savetz.new_env_str);
156 }
157}
158
159
160time_t icaltime_as_timet(struct icaltimetype tt)
161{
162 struct tm stm;
163 time_t t;
164
165 memset(&stm,0,sizeof( struct tm));
166
167 if(icaltime_is_null_time(tt)) {
168 return 0;
169 }
170
171 stm.tm_sec = tt.second;
172 stm.tm_min = tt.minute;
173 stm.tm_hour = tt.hour;
174 stm.tm_mday = tt.day;
175 stm.tm_mon = tt.month-1;
176 stm.tm_year = tt.year-1900;
177 stm.tm_isdst = -1;
178
179 if(tt.is_utc == 1 || tt.is_date == 1){
180 struct set_tz_save old_tz = set_tz("UTC");
181 t = mktime(&stm);
182 unset_tz(old_tz);
183 } else {
184 t = mktime(&stm);
185 }
186
187 return t;
188
189}
190
191char* icaltime_as_ical_string(struct icaltimetype tt)
192{
193 size_t size = 17;
194 char* buf = icalmemory_new_buffer(size);
195
196 if(tt.is_date){
197 snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day);
198 } else {
199 char* fmt;
200 if(tt.is_utc){
201 fmt = "%04d%02d%02dT%02d%02d%02dZ";
202 } else {
203 fmt = "%04d%02d%02dT%02d%02d%02d";
204 }
205 snprintf(buf, size,fmt,tt.year,tt.month,tt.day,
206 tt.hour,tt.minute,tt.second);
207 }
208
209 icalmemory_add_tmp_buffer(buf);
210
211 return buf;
212
213}
214
215
216/* convert tt, of timezone tzid, into a utc time */
217struct icaltimetype icaltime_as_utc(struct icaltimetype tt,const char* tzid)
218{
219 int tzid_offset;
220
221 if(tt.is_utc == 1 || tt.is_date == 1){
222 return tt;
223 }
224
225 tzid_offset = icaltime_utc_offset(tt,tzid);
226
227 tt.second -= tzid_offset;
228
229 tt.is_utc = 1;
230
231 return icaltime_normalize(tt);
232}
233
234/* convert tt, a time in UTC, into a time in timezone tzid */
235struct icaltimetype icaltime_as_zone(struct icaltimetype tt,const char* tzid)
236{
237 int tzid_offset;
238
239 tzid_offset = icaltime_utc_offset(tt,tzid);
240
241 tt.second += tzid_offset;
242
243 tt.is_utc = 0;
244
245 return icaltime_normalize(tt);
246
247}
248
249
250/* Return the offset of the named zone as seconds. tt is a time
251 indicating the date for which you want the offset */
252int icaltime_utc_offset(struct icaltimetype ictt, const char* tzid)
253{
254
255 time_t tt = icaltime_as_timet(ictt);
256 time_t offset_tt;
257 struct tm gtm;
258 struct set_tz_save old_tz;
259
260 if(tzid != 0){
261 old_tz = set_tz(tzid);
262 }
263
264 /* Mis-interpret a UTC broken out time as local time */
265 gtm = *(gmtime(&tt));
266 gtm.tm_isdst = localtime(&tt)->tm_isdst;
267 offset_tt = mktime(&gtm);
268
269 if(tzid != 0){
270 unset_tz(old_tz);
271 }
272
273 return tt-offset_tt;
274}
275
276
277
278/* Normalize by converting from localtime to utc and back to local
279 time. This uses localtime because localtime and mktime are inverses
280 of each other */
281
282struct icaltimetype icaltime_normalize(struct icaltimetype tt)
283{
284 struct tm stm;
285 time_t tut;
286
287 memset(&stm,0,sizeof( struct tm));
288
289 stm.tm_sec = tt.second;
290 stm.tm_min = tt.minute;
291 stm.tm_hour = tt.hour;
292 stm.tm_mday = tt.day;
293 stm.tm_mon = tt.month-1;
294 stm.tm_year = tt.year-1900;
295 stm.tm_isdst = -1; /* prevents mktime from changing hour based on
296 daylight savings */
297
298 tut = mktime(&stm);
299
300 stm = *(localtime(&tut));
301
302 tt.second = stm.tm_sec;
303 tt.minute = stm.tm_min;
304 tt.hour = stm.tm_hour;
305 tt.day = stm.tm_mday;
306 tt.month = stm.tm_mon +1;
307 tt.year = stm.tm_year+1900;
308
309 return tt;
310}
311
312
313#ifndef ICAL_NO_LIBICAL
314#include "icalvalue.h"
315
316struct icaltimetype icaltime_from_string(const char* str)
317{
318 struct icaltimetype tt = icaltime_null_time();
319 int size;
320
321 icalerror_check_arg_re(str!=0,"str",icaltime_null_time());
322
323 size = strlen(str);
324
325 if(size == 15) { /* floating time */
326 tt.is_utc = 0;
327 tt.is_date = 0;
328 } else if (size == 16) { /* UTC time, ends in 'Z'*/
329 tt.is_utc = 1;
330 tt.is_date = 0;
331
332 if(str[15] != 'Z'){
333 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
334 return icaltime_null_time();
335 }
336
337 } else if (size == 8) { /* A DATE */
338 tt.is_utc = 1;
339 tt.is_date = 1;
340 } else { /* error */
341 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
342 return icaltime_null_time();
343 }
344
345 if(tt.is_date == 1){
346 sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day);
347 } else {
348 char tsep;
349 sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day,
350 &tsep,&tt.hour,&tt.minute,&tt.second);
351
352 if(tsep != 'T'){
353 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
354 return icaltime_null_time();
355 }
356
357 }
358
359 return tt;
360}
361#endif
362
363char ctime_str[20];
364char* icaltime_as_ctime(struct icaltimetype t)
365{
366 time_t tt;
367
368 tt = icaltime_as_timet(t);
369 sprintf(ctime_str,"%s",ctime(&tt));
370
371 ctime_str[strlen(ctime_str)-1] = 0;
372
373 return ctime_str;
374}
375
376
377short days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
378
379short icaltime_days_in_month(short month,short year)
380{
381
382 int is_leap =0;
383 int days = days_in_month[month];
384
385 assert(month > 0);
386 assert(month <= 12);
387
388 if( (year % 4 == 0 && year % 100 != 0) ||
389 year % 400 == 0){
390 is_leap =1;
391 }
392
393 if( month == 2){
394 days += is_leap;
395 }
396
397 return days;
398}
399
400/* 1-> Sunday, 7->Saturday */
401short icaltime_day_of_week(struct icaltimetype t){
402
403 time_t tt = icaltime_as_timet(t);
404 struct tm *tm;
405
406 if(t.is_utc == 1 || t.is_date == 1){
407 tm = gmtime(&tt);
408 } else {
409 tm = localtime(&tt);
410 }
411
412 return tm->tm_wday+1;
413}
414
415/* Day of the year that the first day of the week (Sunday) is on */
416short icaltime_start_doy_of_week(struct icaltimetype t){
417 time_t tt = icaltime_as_timet(t);
418 time_t start_tt;
419 struct tm *stm;
420 int syear;
421
422 stm = gmtime(&tt);
423 syear = stm->tm_year;
424
425 start_tt = tt - stm->tm_wday*(60*60*24);
426
427 stm = gmtime(&start_tt);
428
429 if(syear == stm->tm_year){
430 return stm->tm_yday+1;
431 } else {
432 /* return negative to indicate that start of week is in
433 previous year. */
434 int is_leap = 0;
435 int year = stm->tm_year;
436
437 if( (year % 4 == 0 && year % 100 != 0) ||
438 year % 400 == 0){
439 is_leap =1;
440 }
441
442 return (stm->tm_yday+1)-(365+is_leap);
443 }
444
445}
446
447short icaltime_week_number(struct icaltimetype ictt)
448{
449 char str[5];
450 time_t t = icaltime_as_timet(ictt);
451 int week_no;
452
453 strftime(str,5,"%V", gmtime(&t));
454
455 week_no = atoi(str);
456
457 return week_no;
458
459}
460
461
462short icaltime_day_of_year(struct icaltimetype t){
463 time_t tt;
464 struct tm *stm;
465 struct set_tz_save old_tz;
466
467 tt = icaltime_as_timet(t);
468
469 old_tz = set_tz("UTC");
470 stm = localtime(&tt);
471 unset_tz(old_tz);
472
473 return stm->tm_yday+1;
474
475}
476
477/* Jan 1 is day #1, not 0 */
478struct icaltimetype icaltime_from_day_of_year(short doy, short year)
479{
480 struct tm stm;
481 time_t tt;
482 struct set_tz_save old_tz;
483
484 /* Get the time of january 1 of this year*/
485 memset(&stm,0,sizeof(struct tm));
486 stm.tm_year = year-1900;
487 stm.tm_mday = 1;
488
489 old_tz = set_tz("UTC");
490 tt = mktime(&stm);
491 unset_tz(old_tz);
492
493
494 /* Now add in the days */
495
496 doy--;
497 tt += doy *60*60*24;
498
499 return icaltime_from_timet(tt, 1);
500}
501
502struct icaltimetype icaltime_null_time()
503{
504 struct icaltimetype t;
505 memset(&t,0,sizeof(struct icaltimetype));
506
507 return t;
508}
509
510
511int icaltime_is_valid_time(struct icaltimetype t){
512 if(t.is_utc > 1 || t.is_utc < 0 ||
513 t.year < 0 || t.year > 3000 ||
514 t.is_date > 1 || t.is_date < 0){
515 return 0;
516 } else {
517 return 1;
518 }
519
520}
521
522int icaltime_is_null_time(struct icaltimetype t)
523{
524 if (t.second +t.minute+t.hour+t.day+t.month+t.year == 0){
525 return 1;
526 }
527
528 return 0;
529
530}
531
532int icaltime_compare(struct icaltimetype a,struct icaltimetype b)
533{
534 time_t t1 = icaltime_as_timet(a);
535 time_t t2 = icaltime_as_timet(b);
536
537 if (t1 > t2) {
538 return 1;
539 } else if (t1 < t2) {
540 return -1;
541 } else {
542 return 0;
543 }
544
545}
546
547int
548icaltime_compare_date_only (struct icaltimetype a, struct icaltimetype b)
549{
550 time_t t1;
551 time_t t2;
552
553 if (a.year == b.year && a.month == b.month && a.day == b.day)
554 return 0;
555
556 t1 = icaltime_as_timet (a);
557 t2 = icaltime_as_timet (b);
558
559 if (t1 > t2)
560 return 1;
561 else if (t1 < t2)
562 return -1;
563 else {
564 /* not reached */
565 assert (0);
566 return 0;
567 }
568}
569
570
571/* These are defined in icalduration.c:
572struct icaltimetype icaltime_add(struct icaltimetype t,
573 struct icaldurationtype d)
574struct icaldurationtype icaltime_subtract(struct icaltimetype t1,
575 struct icaltimetype t2)
576*/
577