diff options
Diffstat (limited to 'calendar/cal-util/timeutil.c')
-rw-r--r-- | calendar/cal-util/timeutil.c | 501 |
1 files changed, 501 insertions, 0 deletions
diff --git a/calendar/cal-util/timeutil.c b/calendar/cal-util/timeutil.c new file mode 100644 index 0000000000..7ddc0e04d4 --- /dev/null +++ b/calendar/cal-util/timeutil.c @@ -0,0 +1,501 @@ +/* Miscellaneous time-related utilities + * + * Copyright (C) 1998 The Free Software Foundation + * + * Authors: Federico Mena <federico@nuclecu.unam.mx> + * Miguel de Icaza <miguel@nuclecu.unam.mx> + */ + +#include <libgnome/libgnome.h> +#include <string.h> +#include "timeutil.h" + +#define digit_at(x,y) (x [y] - '0') + +time_t +time_from_isodate (char *str) +{ + struct tm my_tm; + time_t t; + + if (strlen (str) < 14) + return -1; + + my_tm.tm_year = (digit_at (str, 0) * 1000 + digit_at (str, 1) * 100 + + digit_at (str, 2) * 10 + digit_at (str, 3)) - 1900; + + my_tm.tm_mon = digit_at (str, 4) * 10 + digit_at (str, 5) - 1; + my_tm.tm_mday = digit_at (str, 6) * 10 + digit_at (str, 7); + my_tm.tm_hour = digit_at (str, 9) * 10 + digit_at (str, 10); + my_tm.tm_min = digit_at (str, 11) * 10 + digit_at (str, 12); + my_tm.tm_sec = digit_at (str, 13) * 10 + digit_at (str, 14); + my_tm.tm_isdst = -1; + + t = mktime (&my_tm); + + if (str [15] == 'Z') +#if defined(HAVE_TM_GMTOFF) + t -= my_tm.tm_gmtoff +#elsif defined(HAVE_TIMEZONE) + t -= timezone +#endif + ; + + return t; +} + +void +print_time_t (time_t t) +{ + struct tm *tm = localtime (&t); + + printf ("TIEMPO: %d/%d/%d %d:%d:%d\n", + tm->tm_mon+1, tm->tm_mday, tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +int +get_time_t_hour (time_t t) +{ + struct tm *tm; + + tm = localtime (&t); + return tm->tm_hour; +} + +char * +isodate_from_time_t (time_t t) +{ + struct tm *tm; + static char isotime [40]; + + tm = localtime (&t); + strftime (isotime, sizeof (isotime)-1, "%Y%m%dT%H%M%S", tm); + return isotime; +} + +time_t +time_from_start_duration (time_t start, char *duration) +{ + printf ("Not yet implemented\n"); + return 0; +} + +char * +format_simple_hour (int hour, int use_am_pm) +{ + static char buf[256]; + + /* I don't know whether this is the best way to internationalize it. + * Does any language use different conventions? - Federico + */ + + if (use_am_pm) + g_snprintf (buf, sizeof(buf), "%d%s", + (hour == 0) ? 12 : (hour > 12) ? (hour - 12) : hour, + (hour < 12) ? _("am") : _("pm")); + else + g_snprintf (buf, sizeof(buf), "%02d%s", hour, _("h")); + + return buf; + +} + +time_t +time_add_minutes (time_t time, int minutes) +{ + struct tm *tm = localtime (&time); + time_t new_time; + + tm->tm_min += minutes; + if ((new_time = mktime (tm)) == -1){ + g_warning ("mktime could not handling adding a day with\n"); + print_time_t (time); + return time; + } + return new_time; +} + +time_t +time_add_day (time_t time, int days) +{ + struct tm *tm = localtime (&time); + time_t new_time; + int dst_flag = tm->tm_isdst; + + tm->tm_mday += days; + + if ((new_time = mktime (tm)) == -1){ + g_warning ("mktime could not handling adding a day with\n"); + print_time_t (time); + return time; + } + + if (dst_flag > tm->tm_isdst){ + tm->tm_hour++; + new_time += 3600; + } else if (dst_flag < tm->tm_isdst){ + tm->tm_hour--; + new_time -= 3600; + } + + return new_time; +} + +time_t +time_add_week (time_t time, int weeks) +{ + return time_add_day (time, weeks * 7); +} + +time_t +time_add_month (time_t time, int months) +{ + struct tm *tm = localtime (&time); + time_t new_time; + int mday; + + mday = tm->tm_mday; + + tm->tm_mon += months; + tm->tm_isdst = -1; + if ((new_time = mktime (tm)) == -1){ + g_warning ("mktime could not handling adding a month with\n"); + print_time_t (time); + return time; + } + tm = localtime (&new_time); + if (tm->tm_mday < mday){ + tm->tm_mon--; + tm->tm_mday = time_days_in_month (tm->tm_year+1900, tm->tm_mon); + return new_time = mktime (tm); + } + else + return new_time; +} + +time_t +time_add_year (time_t time, int years) +{ + struct tm *tm = localtime (&time); + time_t new_time; + + tm->tm_year += years; + if ((new_time = mktime (tm)) == -1){ + g_warning ("mktime could not handling adding a year with\n"); + print_time_t (time); + return time; + } + return new_time; +} + +time_t +time_day_hour (time_t t, int hour) +{ + struct tm tm; + + tm = *localtime (&t); + tm.tm_hour = hour; + tm.tm_min = 0; + tm.tm_sec = 0; + + return mktime (&tm); +} + +/* Number of days in a month, for normal and leap years */ +static const int days_in_month[2][12] = { + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +/* Returns whether the specified year is a leap year */ +static int +is_leap_year (int year) +{ + if (year <= 1752) + return !(year % 4); + else + return (!(year % 4) && (year % 100)) || !(year % 400); +} + +int +time_days_in_month (int year, int month) +{ + g_return_val_if_fail (year >= 1900, 0); + g_return_val_if_fail ((month >= 0) && (month < 12), 0); + + return days_in_month [is_leap_year (year)][month]; +} + +time_t +time_from_day (int year, int month, int day) +{ + struct tm tm; + + memset (&tm, 0, sizeof (tm)); + tm.tm_year = year - 1900; + tm.tm_mon = month; + tm.tm_mday = day; + + return mktime (&tm); +} + +time_t +time_year_begin (time_t t) +{ + struct tm tm; + + tm = *localtime (&t); + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_mon = 0; + tm.tm_mday = 1; + tm.tm_isdst = -1; + + return mktime (&tm); +} + +time_t +time_year_end (time_t t) +{ + struct tm tm; + + tm = *localtime (&t); + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_mon = 0; + tm.tm_mday = 1; + tm.tm_year++; + tm.tm_isdst = -1; + + return mktime (&tm); +} + +time_t +time_month_begin (time_t t) +{ + struct tm tm; + + tm = *localtime (&t); + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_mday = 1; + tm.tm_isdst = -1; + + return mktime (&tm); +} + +time_t +time_month_end (time_t t) +{ + struct tm tm; + + tm = *localtime (&t); + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_mday = 1; + tm.tm_mon++; + tm.tm_isdst = -1; + + return mktime (&tm); +} + +time_t +time_week_begin (time_t t) +{ + struct tm tm; + + /* FIXME: make it take week_starts_on_monday into account */ + + tm = *localtime (&t); + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_mday -= tm.tm_wday; + + return mktime (&tm); +} + +time_t +time_week_end (time_t t) +{ + struct tm tm; + + /* FIXME: make it take week_starts_on_monday into account */ + + tm = *localtime (&t); + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_mday += 7 - tm.tm_wday; + + return mktime (&tm); +} + +time_t +time_day_begin (time_t t) +{ + struct tm tm; + time_t temp = t - 43200; + int dstflag, dstflag2; + + tm = *localtime(&temp); /* one day */ + dstflag = tm.tm_isdst; + + tm = *localtime (&t); + dstflag2 = tm.tm_isdst; + + if (dstflag < dstflag2) + tm.tm_hour = 1; + else + tm.tm_hour = 0; + + tm.tm_min = 0; + tm.tm_sec = 0; + + temp = mktime(&tm); + if (dstflag > dstflag2){ + temp += 3600; + } + + return temp; +} + +time_t +time_day_end (time_t t) +{ + struct tm tm; + time_t temp; + int dstflag, dstflag2; + + t += 10800; + temp = t - 86400; + + tm = *localtime(&temp); /* one day */ + dstflag = tm.tm_isdst; + + tm = *localtime (&t); + dstflag2 = tm.tm_isdst; + + if (dstflag < dstflag2) + tm.tm_hour = 23; + else { + tm.tm_mday++; + tm.tm_hour = 0; + } + tm.tm_min = 0; + tm.tm_sec = 0; + + temp = mktime(&tm); + if(dstflag > dstflag2) { + } + return temp; +} + +static char * +pcat (char *dest, int num, char key) +{ + int c; + + c = sprintf (dest, "%d%c", num, key); + return dest + c; +} + +/* Converts secs into the ISO difftime representation */ +char * +isodiff_from_secs (int secs) +{ + static char buffer [60], *p; + int years, months, weeks, days, hours, minutes; + + years = months = weeks = days = hours = minutes = 0; + + years = secs / (365 * 86400); + secs %= (365 * 86400); + months = secs / (30 * 86400); + secs %= (30 * 86400); + weeks = secs / (7 * 86400); + secs %= (7 * 86400); + days = secs / 86400; + secs %= 86400; + hours = secs / 3600; + secs %= 3600; + minutes = secs / 60; + secs %= 60; + + strcpy (buffer, "P"); + p = buffer + 1; + if (years) + p = pcat (p, years, 'Y'); + if (months) + p = pcat (p, months, 'M'); + if (weeks) + p = pcat (p, weeks, 'W'); + if (days) + p = pcat (p, days, 'D'); + if (hours || minutes || secs){ + *p++ = 'T'; + if (hours) + p = pcat (p, hours, 'H'); + if (minutes) + p = pcat (p, minutes, 'M'); + if (secs) + p = pcat (p, secs, 'S'); + } + + return buffer; +} + +int +isodiff_to_secs (char *str) +{ + int value, time; + int years, months, weeks, days, hours, minutes, seconds; + + value = years = months = weeks = days = hours = minutes = time = seconds = 0; + if (*str != 'P') + return 0; + + str++; + while (*str){ + switch (*str){ + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + value = value * 10 + (*str - '0'); + break; + case 'Y': + years = value; value = 0; + break; + case 'M': + if (time) + minutes = value; + else + months = value; + value = 0; + break; + case 'W': + weeks = value; value = 0; + break; + case 'D': + days = value; value = 0; + break; + case 'T': + value = 0; time = 1; + break; + case 'H': + hours = value; value = 0; + break; + case 'S': + seconds = value; value = 0; + break; + } + str++; + } + return seconds + (minutes * 60) + (hours * 3600) + + (days * 86400) + (weeks * 7 * 86400) + + (months * 30 * 86400) + (years * 365 * 86400); +} |