Back to index

lightning-sunbird  0.9+nobinonly
icaltime.c
Go to the documentation of this file.
00001 /* -*- Mode: C -*-
00002   ======================================================================
00003   FILE: icaltime.c
00004   CREATOR: eric 02 June 2000
00005   
00006   $Id: icaltime.c,v 1.66 2003/02/17 15:19:14 acampi Exp $
00007   $Locker:  $
00008     
00009  (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
00010 
00011  This program is free software; you can redistribute it and/or modify
00012  it under the terms of either: 
00013 
00014     The LGPL as published by the Free Software Foundation, version
00015     2.1, available at: http://www.fsf.org/copyleft/lesser.html
00016 
00017   Or:
00018 
00019     The Mozilla Public License Version 1.0. You may obtain a copy of
00020     the License at http://www.mozilla.org/MPL/
00021 
00022  The Original Code is eric. The Initial Developer of the Original
00023  Code is Eric Busboom
00024 
00025 
00026  ======================================================================*/
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include "config.h"
00030 #endif
00031 
00032 #include "icaltime.h"
00033 #include <assert.h>
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037 #include <time.h>
00038 
00039 #include "astime.h"         /* Julian data handling routines */
00040 
00041 #include "icalerror.h"
00042 #include "icalmemory.h"
00043 
00044 #include "icaltimezone.h"
00045 #include "icalvalue.h"
00046 
00047 #ifdef WIN32
00048 #include <windows.h>
00049 
00050 #define snprintf      _snprintf
00051 #define strcasecmp    stricmp
00052 #endif
00053 
00054 /*
00055  *  Function to convert a struct tm time specification
00056  *  to an ANSI time_t using the specified time zone.
00057  *  This is different from the standard mktime() function
00058  *  in that we dont want the automatic adjustments for
00059  *  local daylight savings time applied to the result.
00060  *  This function expects well-formed input.
00061  */
00062 static time_t make_time(struct tm *tm, int tzm)
00063 {
00064   time_t tim;
00065 
00066   static int days[] = { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 };
00067 
00068   /* check that year specification within range */
00069 
00070   if (tm->tm_year < 70 || tm->tm_year > 138)
00071     return((time_t) -1);
00072 
00073   /* check that month specification within range */
00074 
00075   if (tm->tm_mon < 0 || tm->tm_mon > 11)
00076     return((time_t) -1);
00077 
00078   /* check for upper bound of Jan 17, 2038 (to avoid possibility of
00079      32-bit arithmetic overflow) */
00080   
00081   if (tm->tm_year == 138) {
00082     if (tm->tm_mon > 0)
00083       return((time_t) -1);
00084     else if (tm->tm_mday > 17)
00085       return((time_t) -1);
00086   }
00087 
00088   /*
00089    *  calculate elapsed days since start of the epoch (midnight Jan
00090    *  1st, 1970 UTC) 17 = number of leap years between 1900 and 1970
00091    *  (number of leap days to subtract)
00092    */
00093 
00094   tim = (tm->tm_year - 70) * 365 + ((tm->tm_year - 1) / 4) - 17;
00095 
00096   /* add number of days elapsed in the current year */
00097 
00098   tim += days[tm->tm_mon];
00099 
00100   /* check and adjust for leap years (the leap year check only valid
00101      during the 32-bit era */
00102 
00103   if ((tm->tm_year & 3) == 0 && tm->tm_mon > 1)
00104     tim += 1;
00105 
00106   /* elapsed days to current date */
00107 
00108   tim += tm->tm_mday;
00109 
00110 
00111   /* calculate elapsed hours since start of the epoch */
00112 
00113   tim = tim * 24 + tm->tm_hour;
00114 
00115   /* calculate elapsed minutes since start of the epoch */
00116 
00117   tim = tim * 60 + tm->tm_min;
00118   
00119   /* adjust per time zone specification */
00120   
00121   tim -= tzm;
00122   
00123   /* calculate elapsed seconds since start of the epoch */
00124   
00125   tim = tim * 60 + tm->tm_sec;
00126   
00127   /* return number of seconds since start of the epoch */
00128   
00129   return(tim);
00130 }
00131 
00143 struct icaltimetype 
00144 icaltime_from_timet(const time_t tm, const int is_date)
00145 {
00146 #ifndef NO_WARN_DEPRECATED
00147        icalerror_warn("icaltime_from_timet() is DEPRECATED, use icaltime_from_timet_with_zone() instead");
00148 #endif
00149 
00150        return icaltime_from_timet_with_zone(tm, is_date, 0);
00151 }
00152 
00153 
00178 struct icaltimetype 
00179 icaltime_from_timet_with_zone(const time_t tm, const int is_date,
00180        const icaltimezone *zone)
00181 {
00182     struct icaltimetype tt = icaltime_null_time();
00183     struct tm t;
00184     icaltimezone *utc_zone;
00185 
00186     /* Convert the time_t to a struct tm. We can trust gmtime for this. */
00187 #ifdef HAVE_GMTIME_R
00188     gmtime_r(&tm, &t);
00189 #else
00190     {
00191        struct tm *t_ptr = gmtime(&tm);
00192        t = *t_ptr;
00193     }
00194 #endif
00195 
00196     tt.year   = t.tm_year + 1900;
00197     tt.month  = t.tm_mon + 1;
00198     tt.day    = t.tm_mday;
00199 
00200     if (is_date) { 
00201        tt.is_date = 1;
00202        return tt;
00203     }
00204 
00205     tt.hour   = t.tm_hour;
00206     tt.minute = t.tm_min;
00207     tt.second = t.tm_sec;
00208 
00209     /* If it's a floating time, we don't do any conversion. */
00210     if (zone == NULL) {
00211        return tt;
00212     }
00213 
00214     utc_zone = icaltimezone_get_utc_timezone ();
00215     tt.is_utc = (zone == utc_zone) ? 1 : 0;
00216     tt.zone = zone;
00217 
00218     return tt;
00219 }
00220 
00225 struct icaltimetype icaltime_current_time_with_zone(const icaltimezone *zone)
00226 {
00227     return icaltime_from_timet_with_zone (time (NULL), 0, zone);
00228 }
00229 
00234 struct icaltimetype icaltime_today(void)
00235 {
00236     return icaltime_from_timet_with_zone (time (NULL), 1, NULL);
00237 }
00238 
00247 time_t icaltime_as_timet(const struct icaltimetype tt)
00248 {
00249     struct tm stm;
00250     time_t t;
00251 
00252     /* If the time is the special null time, return 0. */
00253     if (icaltime_is_null_time(tt)) {
00254        return 0;
00255     }
00256 
00257     /* Copy the icaltimetype to a struct tm. */
00258     memset (&stm, 0, sizeof (struct tm));
00259 
00260     if (icaltime_is_date(tt)) {
00261        stm.tm_sec = stm.tm_min = stm.tm_hour = 0;
00262     } else {
00263        stm.tm_sec = tt.second;
00264        stm.tm_min = tt.minute;
00265        stm.tm_hour = tt.hour;
00266     }
00267 
00268     stm.tm_mday = tt.day;
00269     stm.tm_mon = tt.month-1;
00270     stm.tm_year = tt.year-1900;
00271     stm.tm_isdst = -1;
00272 
00273     t = make_time(&stm, 0);
00274 
00275     return t;
00276 
00277 }
00278 
00287 time_t icaltime_as_timet_with_zone(const struct icaltimetype _tt,
00288        const icaltimezone *zone)
00289 {
00290     struct icaltimetype tt = _tt;
00291     struct tm stm;
00292     time_t t;
00293 
00294     /* If the time is the special null time, return 0. */
00295     if (icaltime_is_null_time(tt)) {
00296        return 0;
00297     }
00298 
00299     if (zone != NULL) {
00300        tt = icaltime_convert_to_zone(_tt, zone);
00301     }
00302 
00303     /* Copy the icaltimetype to a struct tm. */
00304     memset (&stm, 0, sizeof (struct tm));
00305 
00306     if (icaltime_is_date(tt)) {
00307        stm.tm_sec = stm.tm_min = stm.tm_hour = 0;
00308     } else {
00309        stm.tm_sec = tt.second;
00310        stm.tm_min = tt.minute;
00311        stm.tm_hour = tt.hour;
00312     }
00313 
00314     stm.tm_mday = tt.day;
00315     stm.tm_mon = tt.month-1;
00316     stm.tm_year = tt.year-1900;
00317     stm.tm_isdst = -1;
00318 
00319     t = make_time(&stm, 0);
00320 
00321     return t;
00322 }
00323 
00328 const char* icaltime_as_ical_string(const struct icaltimetype tt)
00329 {
00330     size_t size = 17;
00331     char* buf = icalmemory_new_buffer(size);
00332 
00333     if(tt.is_date){
00334        snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day);
00335     } else {
00336        char* fmt;
00337        if(tt.is_utc){
00338            fmt = "%04d%02d%02dT%02d%02d%02dZ";
00339        } else {
00340            fmt = "%04d%02d%02dT%02d%02d%02d";
00341        }
00342        snprintf(buf, size,fmt,tt.year,tt.month,tt.day,
00343                tt.hour,tt.minute,tt.second);
00344     }
00345     
00346     icalmemory_add_tmp_buffer(buf);
00347 
00348     return buf;
00349 
00350 }
00351 
00361 struct icaltimetype icaltime_normalize(const struct icaltimetype tt)
00362 {
00363        struct icaltimetype ret = tt;
00364        icaltime_adjust(&ret, 0, 0, 0, 0);
00365        return ret;
00366 }
00367 
00368 
00369 
00379 struct icaltimetype icaltime_from_string(const char* str)
00380 {
00381     struct icaltimetype tt = icaltime_null_time();
00382     int size;
00383 
00384     icalerror_check_arg_re(str!=0,"str",icaltime_null_time());
00385 
00386     size = strlen(str);
00387     
00388     if(size == 15) { /* floating time */
00389        tt.is_utc = 0;
00390        tt.is_date = 0;
00391     } else if (size == 16) { /* UTC time, ends in 'Z'*/
00392        if(str[15] != 'Z')
00393            goto FAIL;
00394 
00395        tt.is_utc = 1;
00396        tt.zone = icaltimezone_get_utc_timezone();
00397        tt.is_date = 0;
00398     } else if (size == 8) { /* A DATE */
00399        tt.is_utc = 0;
00400        tt.is_date = 1;
00401     } else { /* error */
00402        goto FAIL;
00403     }
00404 
00405     if(tt.is_date == 1){
00406        if (sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day) < 3)
00407            goto FAIL;
00408     } else {
00409        char tsep;
00410        if (sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day,
00411               &tsep,&tt.hour,&tt.minute,&tt.second) < 7)
00412            goto FAIL;
00413 
00414        if(tsep != 'T')
00415            goto FAIL;
00416     }
00417 
00418     return tt;    
00419 
00420 FAIL:
00421     icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
00422     return icaltime_null_time();
00423 }
00424 
00425 
00426 /* Returns whether the specified year is a leap year. Year is the normal year,
00427    e.g. 2001. */
00428 int
00429 icaltime_is_leap_year (const int year)
00430 {
00431 
00432     if (year <= 1752)
00433         return (year % 4 == 0);
00434     else
00435         return ( (year % 4==0) && (year % 100 !=0 )) || (year % 400 == 0);
00436 }
00437 
00438 static int _days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
00439 
00440 int icaltime_days_in_month(const int month, const int year)
00441 {
00442 
00443     int days = _days_in_month[month];
00444 
00445     assert(month > 0);
00446     assert(month <= 12);
00447 
00448     if( month == 2){
00449        days += icaltime_is_leap_year(year);
00450     }
00451 
00452     return days;
00453 }
00454 
00455 /* 1-> Sunday, 7->Saturday */
00456 int icaltime_day_of_week(const struct icaltimetype t){
00457        UTinstant jt;
00458 
00459        memset(&jt,0,sizeof(UTinstant));
00460 
00461        jt.year = t.year;
00462     jt.month = t.month;
00463     jt.day = t.day;
00464     jt.i_hour = 0;
00465     jt.i_minute = 0;
00466     jt.i_second = 0;
00467 
00468        juldat(&jt);
00469 
00470        return jt.weekday + 1;
00471 }
00472 
00475 int icaltime_start_doy_week(const struct icaltimetype t, int fdow){
00476        UTinstant jt;
00477        int delta;
00478 
00479        memset(&jt,0,sizeof(UTinstant));
00480 
00481        jt.year = t.year;
00482     jt.month = t.month;
00483     jt.day = t.day;
00484     jt.i_hour = 0;
00485     jt.i_minute = 0;
00486     jt.i_second = 0;
00487 
00488        juldat(&jt);
00489        caldat(&jt);
00490 
00491        delta = jt.weekday - (fdow - 1);
00492        if (delta < 0) delta += 7;
00493        return jt.day_of_year - delta;
00494 }
00495 
00500 int icaltime_start_doy_of_week(const struct icaltimetype t){
00501 
00502 #ifndef NO_WARN_DEPRECATED
00503     icalerror_warn("icaltime_start_doy_of_week() is DEPRECATED, use\
00504        icaltime_start_doy_week() instead");
00505 #endif
00506 
00507     return icaltime_start_doy_week(t, 1);
00508 }
00509 
00514 int icaltime_week_number(const struct icaltimetype ictt)
00515 {
00516        UTinstant jt;
00517 
00518        memset(&jt,0,sizeof(UTinstant));
00519 
00520        jt.year = ictt.year;
00521     jt.month = ictt.month;
00522     jt.day = ictt.day;
00523     jt.i_hour = 0;
00524     jt.i_minute = 0;
00525     jt.i_second = 0;
00526 
00527        juldat(&jt);
00528        caldat(&jt);
00529 
00530        return (jt.day_of_year - jt.weekday) / 7;
00531 }
00532 
00533 /* The first array is for non-leap years, the second for leap years*/
00534 static const int days_in_year[2][13] = 
00535 { /* jan feb mar apr may  jun  jul  aug  sep  oct  nov  dec */
00536   {  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 
00537   {  0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
00538 };
00539 
00543 int icaltime_day_of_year(const struct icaltimetype t){
00544   int is_leap = icaltime_is_leap_year (t.year);
00545 
00546   return days_in_year[is_leap][t.month - 1] + t.day;
00547 }
00548 
00553 /* Jan 1 is day #1, not 0 */
00554 struct icaltimetype icaltime_from_day_of_year(const int _doy, const int _year)
00555 {
00556     struct icaltimetype tt = icaltime_null_date();
00557     int is_leap;
00558     int month;
00559     int doy = _doy;
00560     int year = _year;
00561 
00562     is_leap = icaltime_is_leap_year(year);
00563 
00564     /* Zero and neg numbers represent days  of the previous year */
00565     if(doy <1){
00566         year--;
00567         is_leap = icaltime_is_leap_year(year);
00568         doy +=  days_in_year[is_leap][12];
00569     } else if(doy > days_in_year[is_leap][12]){
00570         /* Move on to the next year*/
00571         is_leap = icaltime_is_leap_year(year);
00572         doy -=  days_in_year[is_leap][12];
00573         year++;
00574     }
00575 
00576     tt.year = year;
00577 
00578     for (month = 11; month >= 0; month--) {
00579       if (doy > days_in_year[is_leap][month]) {
00580        tt.month = month + 1;
00581        tt.day = doy - days_in_year[is_leap][month];
00582        break;
00583       }
00584     }
00585 
00586     return tt;
00587 }
00588 
00593 struct icaltimetype icaltime_null_time(void)
00594 {
00595     struct icaltimetype t;
00596     memset(&t,0,sizeof(struct icaltimetype));
00597 
00598     return t;
00599 }
00600 
00605 struct icaltimetype icaltime_null_date(void)
00606 {
00607     struct icaltimetype t;
00608     memset(&t,0,sizeof(struct icaltimetype));
00609 
00610     t.is_date = 1;
00611 
00612     /*
00613      * Init to -1 to match what icalyacc.y used to do.
00614      * Does anything depend on this?
00615      */
00616     t.hour = -1;
00617     t.minute = -1;
00618     t.second = -1;
00619 
00620     return t;
00621 }
00622 
00623 
00629 int icaltime_is_valid_time(const struct icaltimetype t){
00630     if(t.is_utc > 1 || t.is_utc < 0 ||
00631        t.year < 0 || t.year > 3000 ||
00632        t.is_date > 1 || t.is_date < 0){
00633        return 0;
00634     } else {
00635        return 1;
00636     }
00637 
00638 }
00639 
00642 int icaltime_is_date(const struct icaltimetype t) {
00643 
00644        return t.is_date;
00645 }
00646 
00651 int icaltime_is_utc(const struct icaltimetype t) {
00652 
00653        return t.is_utc;
00654 }
00655 
00659 int icaltime_is_null_time(const struct icaltimetype t)
00660 {
00661     if (t.second +t.minute+t.hour+t.day+t.month+t.year == 0){
00662        return 1;
00663     }
00664 
00665     return 0;
00666 
00667 }
00668 
00675 int icaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in) 
00676 {
00677     int retval = 0;
00678     struct icaltimetype a, b;
00679 
00680     a = icaltime_convert_to_zone(a_in, icaltimezone_get_utc_timezone());
00681     b = icaltime_convert_to_zone(b_in, icaltimezone_get_utc_timezone());
00682 
00683     if (a.year > b.year)
00684        retval = 1;
00685     else if (a.year < b.year)
00686        retval = -1;
00687 
00688     else if (a.month > b.month)
00689        retval = 1;
00690     else if (a.month < b.month)
00691        retval = -1;
00692 
00693     else if (a.day > b.day)
00694        retval = 1;
00695     else if (a.day < b.day)
00696        retval = -1;
00697 
00698     /* if both are dates, we are done */
00699     if (a.is_date && b.is_date)
00700        return retval;
00701 
00702     /* else, if we already found a difference, we are done */
00703     else if (retval != 0)
00704        return retval;
00705 
00706     /* else, if only one is a date (and we already know the date part is equal),
00707        then the other is greater */
00708     else if (b.is_date)
00709        retval = 1;
00710     else if (a.is_date)
00711        retval = -1;
00712 
00713     else if (a.hour > b.hour)
00714        retval = 1;
00715     else if (a.hour < b.hour)
00716        retval = -1;
00717 
00718     else if (a.minute > b.minute)
00719        retval = 1;
00720     else if (a.minute < b.minute)
00721        retval = -1;
00722 
00723     else if (a.second > b.second)
00724        retval = 1;
00725     else if (a.second < b.second)
00726        retval = -1;
00727 
00728     return retval;
00729 }
00730 
00735 int
00736 icaltime_compare_date_only(const struct icaltimetype a_in, const struct icaltimetype b_in, icaltimezone *tz)
00737 {
00738     int retval;
00739     struct icaltimetype a, b;
00740 
00741     a = icaltime_convert_to_zone(a_in, tz);
00742     b = icaltime_convert_to_zone(b_in, tz);
00743 
00744     if (a.year > b.year)
00745        retval = 1;
00746     else if (a.year < b.year)
00747        retval = -1;
00748 
00749     else if (a.month > b.month)
00750        retval = 1;
00751     else if (a.month < b.month)
00752        retval = -1;
00753 
00754     else if (a.day > b.day)
00755        retval = 1;
00756     else if (a.day < b.day)
00757        retval = -1;
00758 
00759     else
00760        retval = 0;
00761 
00762     return retval;
00763 }
00764 
00765 /* These are defined in icalduration.c:
00766 struct icaltimetype  icaltime_add(struct icaltimetype t,
00767                               struct icaldurationtype  d)
00768 struct icaldurationtype  icaltime_subtract(struct icaltimetype t1,
00769                                       struct icaltimetype t2)
00770 */
00771 
00772 
00773 
00780 void
00781 icaltime_adjust(struct icaltimetype *tt, const int days, const int hours,
00782        const int minutes, const int seconds) {
00783 
00784     int second, minute, hour, day;
00785     int minutes_overflow, hours_overflow, days_overflow = 0, years_overflow;
00786     int days_in_month;
00787 
00788     /* If we are passed a date make sure to ignore hour minute and second */
00789     if (tt->is_date)
00790        goto IS_DATE;
00791 
00792     /* Add on the seconds. */
00793     second = tt->second + seconds;
00794     tt->second = second % 60;
00795     minutes_overflow = second / 60;
00796     if (tt->second < 0) {
00797        tt->second += 60;
00798        minutes_overflow--;
00799     }
00800 
00801     /* Add on the minutes. */
00802     minute = tt->minute + minutes + minutes_overflow;
00803     tt->minute = minute % 60;
00804     hours_overflow = minute / 60;
00805     if (tt->minute < 0) {
00806        tt->minute += 60;
00807        hours_overflow--;
00808     }
00809 
00810     /* Add on the hours. */
00811     hour = tt->hour + hours + hours_overflow;
00812     tt->hour = hour % 24;
00813     days_overflow = hour / 24;
00814     if (tt->hour < 0) {
00815        tt->hour += 24;
00816        days_overflow--;
00817     }
00818 
00819 IS_DATE:
00820     /* Normalize the month. We do this before handling the day since we may
00821        need to know what month it is to get the number of days in it.
00822        Note that months are 1 to 12, so we have to be a bit careful. */
00823     if (tt->month >= 13) {
00824        years_overflow = (tt->month - 1) / 12;
00825        tt->year += years_overflow;
00826        tt->month -= years_overflow * 12;
00827     } else if (tt->month <= 0) {
00828        /* 0 to -11 is -1 year out, -12 to -23 is -2 years. */
00829        years_overflow = (tt->month / 12) - 1;
00830        tt->year += years_overflow;
00831        tt->month -= years_overflow * 12;
00832     }
00833 
00834     /* Add on the days. */
00835     day = tt->day + days + days_overflow;
00836     if (day > 0) {
00837        for (;;) {
00838            days_in_month = icaltime_days_in_month (tt->month, tt->year);
00839            if (day <= days_in_month)
00840               break;
00841 
00842            tt->month++;
00843            if (tt->month >= 13) {
00844               tt->year++;
00845               tt->month = 1;
00846            }
00847 
00848            day -= days_in_month;
00849        }
00850     } else {
00851        while (day <= 0) {
00852            if (tt->month == 1) {
00853               tt->year--;
00854               tt->month = 12;
00855            } else {
00856               tt->month--;
00857            }
00858 
00859            day += icaltime_days_in_month (tt->month, tt->year);
00860        }
00861     }
00862     tt->day = day;
00863 }
00864 
00875 struct icaltimetype icaltime_convert_to_zone(const struct icaltimetype tt,
00876        icaltimezone *zone) {
00877 
00878        struct icaltimetype ret = tt;
00879 
00880        /* If it's a date do nothing */
00881        if (tt.is_date) {
00882               return ret;
00883        }
00884 
00885        if (tt.zone == zone) {
00886               return ret;
00887        }
00888 
00889        /* If it's a floating time we don't want to adjust the time */
00890        if (tt.zone != NULL) {
00891               icaltimezone_convert_time(&ret, tt.zone, zone);
00892        }
00893 
00894        ret.zone = zone;
00895        if (zone == icaltimezone_get_utc_timezone()) {
00896               ret.is_utc = 1;
00897        } else {
00898               ret.is_utc = 0;
00899        }
00900 
00901        return ret;
00902 }
00903 
00904 const icaltimezone *
00905 icaltime_get_timezone(const struct icaltimetype t) {
00906 
00907        return t.zone;
00908 }
00909 
00910 char *
00911 icaltime_get_tzid(const struct icaltimetype t) {
00912 
00913        if (t.zone != NULL) {
00914               return icaltimezone_get_tzid(t.zone);
00915        } else {
00916               return NULL;
00917        }
00918 }
00919 
00926 struct icaltimetype
00927 icaltime_set_timezone(struct icaltimetype *t, const icaltimezone *zone) {
00928 
00929        /* If it's a date do nothing */
00930        if (t->is_date) {
00931               return *t;
00932        }
00933 
00934        if (t->zone == zone) {
00935               return *t;
00936        }
00937 
00938        t->zone = zone;
00939        if (zone == icaltimezone_get_utc_timezone()) {
00940               t->is_utc = 1;
00941        } else {
00942               t->is_utc = 0;
00943        }
00944 
00945        return *t;
00946 }
00947 
00948 
00961 icaltime_span icaltime_span_new(struct icaltimetype dtstart,
00962                                    struct icaltimetype dtend,
00963                                    int    is_busy)
00964 {
00965   icaltime_span span;
00966 
00967   span.is_busy = is_busy;
00968 
00969   span.start   = icaltime_as_timet_with_zone(dtstart,
00970                                         icaltimezone_get_utc_timezone());
00971 
00972   if (icaltime_is_null_time(dtend)) {
00973     if (!icaltime_is_date(dtstart)) {
00974       /* If dtstart is a DATE-TIME and there is no DTEND nor DURATION
00975         it takes no time */
00976       span.end = span.start;
00977       return span;
00978     } else {
00979       dtend = dtstart;
00980     }
00981   }
00982 
00983   span.end = icaltime_as_timet_with_zone(dtend, icaltimezone_get_utc_timezone());
00984   
00985   if (icaltime_is_date(dtstart)) {
00986     /* no time specified, go until the end of the day..*/
00987     span.end += 60*60*24 - 1;
00988   }
00989   return span;
00990 }
00991 
00992 
01007 int icaltime_span_overlaps(icaltime_span *s1, 
01008                         icaltime_span *s2)
01009 {
01010   /* s1->start in s2 */
01011   if (s1->start > s2->start && s1->start < s2->end)
01012     return 1;
01013 
01014   /* s1->end in s2 */
01015   if (s1->end > s2->start && s1->end < s2->end)
01016     return 1;
01017 
01018   /* s2->start in s1 */
01019   if (s2->start > s1->start && s2->start < s1->end)
01020     return 1;
01021 
01022   /* s2->end in s1 */
01023   if (s2->end > s1->start && s2->end < s1->end)
01024     return 1;
01025 
01026   if (s1->start == s2->start && s1->end == s2->end)
01027     return 1;
01028   
01029   return 0;
01030 }
01031 
01041 int icaltime_span_contains(icaltime_span *s,
01042                         icaltime_span *container)
01043 {
01044 
01045   if ((s->start >= container->start && s->start < container->end) &&
01046       (s->end   <= container->end   && s->end   > container->start))
01047     return 1;
01048   
01049   return 0;
01050 }