Back to index

lightning-sunbird  0.9+nobinonly
Functions
icaltimezone.h File Reference

timezone handling routines More...

#include <stdio.h>
#include "icaltime.h"
#include "icalarray.h"
#include "icalcomponent.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

icaltimezone * icaltimezone_new (void)
 Creates a new icaltimezone.
void icaltimezone_free (icaltimezone *zone, int free_struct)
 Frees all memory used for the icaltimezone.
void icaltimezone_free_builtin_timezones (void)
 Free any builtin timezone information.
icalarray * icaltimezone_get_builtin_timezones (void)
 Returns the array of builtin icaltimezones.
icaltimezone * icaltimezone_get_builtin_timezone (const char *location)
 Returns a single builtin timezone, given its Olson city name.
icaltimezone * icaltimezone_get_builtin_timezone_from_tzid (const char *tzid)
 Returns a single builtin timezone, given its TZID.
icaltimezone * icaltimezone_get_utc_timezone (void)
 Returns the UTC timezone.
char * icaltimezone_get_tzid (icaltimezone *zone)
 Returns the TZID of a timezone.
char * icaltimezone_get_location (icaltimezone *zone)
 Returns the city name of a timezone.
char * icaltimezone_get_tznames (icaltimezone *zone)
 Returns the TZNAME properties used in the latest STANDARD and DAYLIGHT components.
double icaltimezone_get_latitude (icaltimezone *zone)
 Returns the latitude of a builtin timezone.
double icaltimezone_get_longitude (icaltimezone *zone)
 Returns the longitude of a builtin timezone.
icalcomponent * icaltimezone_get_component (icaltimezone *zone)
 Returns the VTIMEZONE component of a timezone.
int icaltimezone_set_component (icaltimezone *zone, icalcomponent *comp)
 Sets the VTIMEZONE component of an icaltimezone, initializing the tzid, location & tzname fields.
void icaltimezone_convert_time (struct icaltimetype *tt, icaltimezone *from_zone, icaltimezone *to_zone)
int icaltimezone_get_utc_offset (icaltimezone *zone, struct icaltimetype *tt, int *is_daylight)
 Calculates the UTC offset of a given local time in the given timezone.
int icaltimezone_get_utc_offset_of_utc_time (icaltimezone *zone, struct icaltimetype *tt, int *is_daylight)
 Calculates the UTC offset of a given UTC time in the given timezone.
icalarray * icaltimezone_array_new (void)
void icaltimezone_array_append_from_vtimezone (icalarray *timezones, icalcomponent *child)
void icaltimezone_array_free (icalarray *timezones)
void set_zone_directory (char *path)
 Set the directory to look for the zonefiles.
void free_zone_directory (void)
 Free memory dedicated to the zonefile directory.
int icaltimezone_dump_changes (icaltimezone *zone, int max_year, FILE *fp)
 Dumps information about changes in the timezone up to and including max_year.

Detailed Description

timezone handling routines

Definition in file icaltimezone.h.


Function Documentation

Free memory dedicated to the zonefile directory.

Definition at line 1674 of file icaltimezone.c.

void icaltimezone_array_append_from_vtimezone ( icalarray *  timezones,
icalcomponent *  child 
)

Definition at line 1238 of file icaltimezone.c.

{
    icaltimezone zone;

    icaltimezone_init (&zone);
    if (icaltimezone_get_vtimezone_properties (&zone, child))
       icalarray_append (timezones, &zone);
}

Here is the call graph for this function:

void icaltimezone_array_free ( icalarray *  timezones)

Definition at line 1250 of file icaltimezone.c.

{
    icaltimezone *zone;
    int i;

       if ( timezones )
       {
              for (i = 0; i < timezones->num_elements; i++) {
              zone = icalarray_element_at (timezones, i);
              icaltimezone_free (zone, 0);
              }

              icalarray_free (timezones);
       }
}

Here is the call graph for this function:

icalarray* icaltimezone_array_new ( void  )

Definition at line 1231 of file icaltimezone.c.

{
    return icalarray_new (sizeof (icaltimezone), 16);
}

Here is the call graph for this function:

void icaltimezone_convert_time ( struct icaltimetype tt,
icaltimezone *  from_zone,
icaltimezone *  to_zone 
)
Converting times between timezones.

Definition at line 746 of file icaltimezone.c.

{
    int utc_offset, is_daylight;

    /* If the time is a DATE value or both timezones are the same, or we are
       converting a floating time, we don't need to do anything. */
    if (icaltime_is_date(*tt) || from_zone == to_zone || from_zone == NULL)
       return;

    /* Convert the time to UTC by getting the UTC offset and subtracting it. */
    utc_offset = icaltimezone_get_utc_offset (from_zone, tt, NULL);
    icaltime_adjust (tt, 0, 0, 0, -utc_offset);

    /* Now we convert the time to the new timezone by getting the UTC offset
       of our UTC time and adding it. */       
    utc_offset = icaltimezone_get_utc_offset_of_utc_time (to_zone, tt,
                                                   &is_daylight);
    tt->is_daylight = is_daylight;
    icaltime_adjust (tt, 0, 0, 0, utc_offset);
}

Here is the call graph for this function:

int icaltimezone_dump_changes ( icaltimezone *  zone,
int  max_year,
FILE fp 
)

Dumps information about changes in the timezone up to and including max_year.

Dumps information about changes in the timezone up to and including max_year.

We compare this output with the output from 'vzic --dump-changes' to make sure that we are consistent. (vzic is the Olson timezone database to VTIMEZONE converter.)

The output format is:

  Zone-Name [tab] Date [tab] Time [tab] UTC-Offset

The Date and Time fields specify the time change in UTC.

The UTC Offset is for local (wall-clock) time. It is the amount of time to add to UTC to get local time.

Definition at line 1587 of file icaltimezone.c.

{
    static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
    icaltimezonechange *zone_change;
    int change_num;
    char buffer[8];

    /* Make sure the changes array is expanded up to the given time. */
    icaltimezone_ensure_coverage (zone, max_year);

#if 0
    printf ("Num changes: %i\n", zone->changes->num_elements);
#endif

    change_num = 0;
    for (change_num = 0; change_num < zone->changes->num_elements; change_num++) {
       zone_change = icalarray_element_at (zone->changes, change_num);

       if (zone_change->year > max_year)
           break;

       fprintf (fp, "%s\t%2i %s %04i\t%2i:%02i:%02i",
              zone->location,
              zone_change->day, months[zone_change->month - 1],
              zone_change->year,
              zone_change->hour, zone_change->minute, zone_change->second);

       /* Wall Clock Time offset from UTC. */
       format_utc_offset (zone_change->utc_offset, buffer);
       fprintf (fp, "\t%s", buffer);

       fprintf (fp, "\n");
    }
       return 1;
}

Here is the call graph for this function:

void icaltimezone_free ( icaltimezone *  zone,
int  free_struct 
)

Frees all memory used for the icaltimezone.

Set free_struct to free the icaltimezone struct as well.

Definition at line 223 of file icaltimezone.c.

{
    icaltimezone_reset (zone);
    if (free_struct)
       free (zone);
}

Here is the call graph for this function:

Free any builtin timezone information.

Accessing timezones.

Definition at line 1287 of file icaltimezone.c.

Here is the call graph for this function:

icaltimezone* icaltimezone_get_builtin_timezone ( const char *  location)

Returns a single builtin timezone, given its Olson city name.

Definition at line 1295 of file icaltimezone.c.

{
    icaltimezone *zone;
    int lower, upper, middle, cmp;
    char *zone_location;

    if (!location || !location[0])
       return NULL;

    if (!strcmp (location, "UTC"))
       return &utc_timezone;

    if (!builtin_timezones)
       icaltimezone_init_builtin_timezones ();

    /* Do a simple binary search. */
    lower = middle = 0;
    upper = builtin_timezones->num_elements;

    while (lower < upper) {
       middle = (lower + upper) / 2;
       zone = icalarray_element_at (builtin_timezones, middle);
       zone_location = icaltimezone_get_location (zone);
       cmp = strcmp (location, zone_location);
       if (cmp == 0)
           return zone;
       else if (cmp < 0)
           upper = middle;
       else
           lower = middle + 1;
    }

    return NULL;
}

Here is the call graph for this function:

icaltimezone* icaltimezone_get_builtin_timezone_from_tzid ( const char *  tzid)

Returns a single builtin timezone, given its TZID.

Definition at line 1333 of file icaltimezone.c.

{
    int num_slashes = 0;
    const char *p, *zone_tzid;
    icaltimezone *zone;

    if (!tzid || !tzid[0])
       return NULL;

    /* Check that the TZID starts with our unique prefix. */
    if (strncmp (tzid, TZID_PREFIX, TZID_PREFIX_LEN))
       return NULL;

    /* Get the location, which is after the 3rd '/' character. */
    p = tzid;
    for (p = tzid; *p; p++) {
       if (*p == '/') {
           num_slashes++;
           if (num_slashes == 3)
              break;
       }
    }

    if (num_slashes != 3)
       return NULL;

    p++;

    /* Now we can use the function to get the builtin timezone from the
       location string. */
    zone = icaltimezone_get_builtin_timezone (p);
    if (!zone)
       return NULL;

    /* Check that the builtin TZID matches exactly. We don't want to return
       a different version of the VTIMEZONE. */
    zone_tzid = icaltimezone_get_tzid (zone);
    if (!strcmp (zone_tzid, tzid))
       return zone;
    else
       return NULL;
}

Here is the call graph for this function:

Returns the array of builtin icaltimezones.

Returns the array of builtin icaltimezones.

This will load and parse the zones.tab file to get the timezone names and their coordinates. It will not load the VTIMEZONE data for any timezones.

Definition at line 1277 of file icaltimezone.c.

Here is the call graph for this function:

icalcomponent* icaltimezone_get_component ( icaltimezone *  zone)

Returns the VTIMEZONE component of a timezone.

Definition at line 1205 of file icaltimezone.c.

{
    /* If this is a floating time, without a timezone, return NULL. */
    if (!zone)
       return NULL;

    if (!zone->component)
       icaltimezone_load_builtin_timezone (zone);

    return zone->component;
}

Here is the call graph for this function:

double icaltimezone_get_latitude ( icaltimezone *  zone)

Returns the latitude of a builtin timezone.

Definition at line 1177 of file icaltimezone.c.

{
    /* If this is a floating time, without a timezone, return 0. */
    if (!zone)
       return 0.0;

    /* Note that for builtin timezones this comes from zones.tab so we don't
       need to check the timezone is loaded here. */
    return zone->latitude;
}
char* icaltimezone_get_location ( icaltimezone *  zone)

Returns the city name of a timezone.

Definition at line 1149 of file icaltimezone.c.

{
    /* If this is a floating time, without a timezone, return NULL. */
    if (!zone)
       return NULL;

    /* Note that for builtin timezones this comes from zones.tab so we don't
       need to check the timezone is loaded here. */
    return zone->location;
}
double icaltimezone_get_longitude ( icaltimezone *  zone)

Returns the longitude of a builtin timezone.

Definition at line 1191 of file icaltimezone.c.

{
    /* If this is a floating time, without a timezone, return 0. */
    if (!zone)
       return 0.0;

    /* Note that for builtin timezones this comes from zones.tab so we don't
       need to check the timezone is loaded here. */
    return zone->longitude;
}
char* icaltimezone_get_tzid ( icaltimezone *  zone)

Returns the TZID of a timezone.

Definition at line 1135 of file icaltimezone.c.

{
    /* If this is a floating time, without a timezone, return NULL. */
    if (!zone)
       return NULL;

    if (!zone->tzid)
       icaltimezone_load_builtin_timezone (zone);

    return zone->tzid;
}

Here is the call graph for this function:

char* icaltimezone_get_tznames ( icaltimezone *  zone)

Returns the TZNAME properties used in the latest STANDARD and DAYLIGHT components.

If they are the same it will return just one, e.g. "LMT". If they are different it will format them like "EST/EDT". Note that this may also return NULL.

Definition at line 1162 of file icaltimezone.c.

{
    /* If this is a floating time, without a timezone, return NULL. */
    if (!zone)
       return NULL;

    if (!zone->component)
       icaltimezone_load_builtin_timezone (zone);

    return zone->tznames;
}

Here is the call graph for this function:

int icaltimezone_get_utc_offset ( icaltimezone *  zone,
struct icaltimetype tt,
int is_daylight 
)

Calculates the UTC offset of a given local time in the given timezone.

Getting offsets from UTC. It is the number of seconds to add to UTC to get local
time. The is_daylight flag is set to 1 if the time is in daylight-savings time.
Deprecated:
This API wasn't updated when we changed icaltimetype to contain its own timezone.

Also, this takes a pointer instead of the struct.

Definition at line 779 of file icaltimezone.c.

{
    icaltimezonechange *zone_change, *prev_zone_change, tt_change, tmp_change;
    int change_num, step, utc_offset_change, cmp;
    int change_num_to_use;
    int want_daylight;

    if (tt == NULL)
       return 0;

    if (is_daylight)
       *is_daylight = 0;

    /* For local times and UTC return 0. */
    if (zone == NULL || zone == &utc_timezone)
       return 0;

    /* Use the builtin icaltimezone if possible. */
    if (zone->builtin_timezone)
       zone = zone->builtin_timezone;

    /* Make sure the changes array is expanded up to the given time. */
    icaltimezone_ensure_coverage (zone, tt->year);

    if (!zone->changes || zone->changes->num_elements == 0)
       return 0;

    /* Copy the time parts of the icaltimetype to an icaltimezonechange so we
       can use our comparison function on it. */
    tt_change.year   = tt->year;
    tt_change.month  = tt->month;
    tt_change.day    = tt->day;
    tt_change.hour   = tt->hour;
    tt_change.minute = tt->minute;
    tt_change.second = tt->second;

    /* This should find a change close to the time, either the change before
       it or the change after it. */
    change_num = icaltimezone_find_nearby_change (zone, &tt_change);

    /* Sanity check. */
    icalerror_assert (change_num >= 0,
                    "Negative timezone change index");
    icalerror_assert (change_num < zone->changes->num_elements,
                    "Timezone change index out of bounds");

    /* Now move backwards or forwards to find the timezone change that applies
       to tt. It should only have to do 1 or 2 steps. */
    zone_change = icalarray_element_at (zone->changes, change_num);
    step = 1;
    change_num_to_use = -1;
    for (;;) {
       /* Copy the change, so we can adjust it. */
       tmp_change = *zone_change;

       /* If the clock is going backward, check if it is in the region of time
          that is used twice. If it is, use the change with the daylight
          setting which matches tt, or use standard if we don't know. */
       if (tmp_change.utc_offset < tmp_change.prev_utc_offset) {
           /* If the time change is at 2:00AM local time and the clock is
              going back to 1:00AM we adjust the change to 1:00AM. We may
              have the wrong change but we'll figure that out later. */
           icaltimezone_adjust_change (&tmp_change, 0, 0, 0,
                                   tmp_change.utc_offset);
       } else {
           icaltimezone_adjust_change (&tmp_change, 0, 0, 0,
                                   tmp_change.prev_utc_offset);
       }

       cmp = icaltimezone_compare_change_fn (&tt_change, &tmp_change);

       /* If the given time is on or after this change, then this change may
          apply, but we continue as a later change may be the right one.
          If the given time is before this change, then if we have already
          found a change which applies we can use that, else we need to step
          backwards. */
       if (cmp >= 0)
           change_num_to_use = change_num;
       else
           step = -1;

       /* If we are stepping backwards through the changes and we have found
          a change that applies, then we know this is the change to use so
          we exit the loop. */
       if (step == -1 && change_num_to_use != -1)
           break;

       change_num += step;

       /* If we go past the start of the changes array, then we have no data
          for this time so we return a UTC offset of 0. */
       if (change_num < 0)
           return 0;

       if (change_num >= zone->changes->num_elements)
           break;

       zone_change = icalarray_element_at (zone->changes, change_num);
    }

    /* If we didn't find a change to use, then we have a bug! */
    icalerror_assert (change_num_to_use != -1,
                    "No applicable timezone change found");

    /* Now we just need to check if the time is in the overlapped region of
       time when clocks go back. */
    zone_change = icalarray_element_at (zone->changes, change_num_to_use);

    utc_offset_change = zone_change->utc_offset - zone_change->prev_utc_offset;
    if (utc_offset_change < 0 && change_num_to_use > 0) {
       tmp_change = *zone_change;
       icaltimezone_adjust_change (&tmp_change, 0, 0, 0,
                                tmp_change.prev_utc_offset);

       if (icaltimezone_compare_change_fn (&tt_change, &tmp_change) < 0) {
           /* The time is in the overlapped region, so we may need to use
              either the current zone_change or the previous one. If the
              time has the is_daylight field set we use the matching change,
              else we use the change with standard time. */
           prev_zone_change = icalarray_element_at (zone->changes,
                                               change_num_to_use - 1);

           /* I was going to add an is_daylight flag to struct icaltimetype,
              but iCalendar doesn't let us distinguish between standard and
              daylight time anyway, so there's no point. So we just use the
              standard time instead. */
           want_daylight = (tt->is_daylight == 1) ? 1 : 0;

#if 0
           if (zone_change->is_daylight == prev_zone_change->is_daylight)
              printf (" **** Same is_daylight setting\n");
#endif

           if (zone_change->is_daylight != want_daylight
              && prev_zone_change->is_daylight == want_daylight)
              zone_change = prev_zone_change;
       }
    }

    /* Now we know exactly which timezone change applies to the time, so
       we can return the UTC offset and whether it is a daylight time. */
    if (is_daylight)
       *is_daylight = zone_change->is_daylight;
    return zone_change->utc_offset;
}

Here is the call graph for this function:

int icaltimezone_get_utc_offset_of_utc_time ( icaltimezone *  zone,
struct icaltimetype tt,
int is_daylight 
)

Calculates the UTC offset of a given UTC time in the given timezone.

It is the number of seconds to add to UTC to get local time. The is_daylight flag is set to 1 if the time is in daylight-savings time.

Deprecated:
This API wasn't updated when we changed icaltimetype to contain its own timezone.

Also, this takes a pointer instead of the struct. It is the number of seconds to add to UTC to get local time. The is_daylight flag is set to 1 if the time is in daylight-savings time.

Definition at line 935 of file icaltimezone.c.

{
    icaltimezonechange *zone_change, tt_change, tmp_change;
    int change_num, step, change_num_to_use;

    if (is_daylight)
       *is_daylight = 0;

    /* For local times and UTC return 0. */
    if (zone == NULL || zone == &utc_timezone)
       return 0;

    /* Use the builtin icaltimezone if possible. */
    if (zone->builtin_timezone)
       zone = zone->builtin_timezone;

    /* Make sure the changes array is expanded up to the given time. */
    icaltimezone_ensure_coverage (zone, tt->year);

    if (!zone->changes || zone->changes->num_elements == 0)
       return 0;

    /* Copy the time parts of the icaltimetype to an icaltimezonechange so we
       can use our comparison function on it. */
    tt_change.year   = tt->year;
    tt_change.month  = tt->month;
    tt_change.day    = tt->day;
    tt_change.hour   = tt->hour;
    tt_change.minute = tt->minute;
    tt_change.second = tt->second;

    /* This should find a change close to the time, either the change before
       it or the change after it. */
    change_num = icaltimezone_find_nearby_change (zone, &tt_change);

    /* Sanity check. */
    icalerror_assert (change_num >= 0,
                    "Negative timezone change index");
    icalerror_assert (change_num < zone->changes->num_elements,
                    "Timezone change index out of bounds");

    /* Now move backwards or forwards to find the timezone change that applies
       to tt. It should only have to do 1 or 2 steps. */
    zone_change = icalarray_element_at (zone->changes, change_num);
    step = 1;
    change_num_to_use = -1;
    for (;;) {
       /* Copy the change and adjust it to UTC. */
       tmp_change = *zone_change;

       /* If the given time is on or after this change, then this change may
          apply, but we continue as a later change may be the right one.
          If the given time is before this change, then if we have already
          found a change which applies we can use that, else we need to step
          backwards. */
       if (icaltimezone_compare_change_fn (&tt_change, &tmp_change) >= 0)
           change_num_to_use = change_num;
       else
           step = -1;

       /* If we are stepping backwards through the changes and we have found
          a change that applies, then we know this is the change to use so
          we exit the loop. */
       if (step == -1 && change_num_to_use != -1)
           break;

       change_num += step;

       /* If we go past the start of the changes array, then we have no data
          for this time so we return a UTC offset of 0. */
       if (change_num < 0)
           return 0;

       if (change_num >= zone->changes->num_elements)
           break;

       zone_change = icalarray_element_at (zone->changes, change_num);
    }

    /* If we didn't find a change to use, then we have a bug! */
    icalerror_assert (change_num_to_use != -1,
                    "No applicable timezone change found");

    /* Now we know exactly which timezone change applies to the time, so
       we can return the UTC offset and whether it is a daylight time. */
    zone_change = icalarray_element_at (zone->changes, change_num_to_use);
    if (is_daylight)
       *is_daylight = zone_change->is_daylight;

    return zone_change->utc_offset;
}

Here is the call graph for this function:

icaltimezone* icaltimezone_get_utc_timezone ( void  )

Returns the UTC timezone.

Definition at line 1379 of file icaltimezone.c.

Here is the call graph for this function:

icaltimezone* icaltimezone_new ( void  )

Creates a new icaltimezone.

Creating/Destroying individual icaltimezones.

Definition at line 205 of file icaltimezone.c.

{
    icaltimezone *zone;

    zone = (icaltimezone*) malloc (sizeof (icaltimezone));
    if (!zone) {
       icalerror_set_errno (ICAL_NEWFAILED_ERROR);
       return NULL;
    }

    icaltimezone_init (zone);

    return zone;
}

Here is the call graph for this function:

int icaltimezone_set_component ( icaltimezone *  zone,
icalcomponent *  comp 
)

Sets the VTIMEZONE component of an icaltimezone, initializing the tzid, location & tzname fields.

It returns 1 on success or 0 on failure, i.e. no TZID was found.

Definition at line 1222 of file icaltimezone.c.

Here is the call graph for this function:

void set_zone_directory ( char *  path)

Set the directory to look for the zonefiles.

Definition at line 1665 of file icaltimezone.c.