aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/cal-util/timeutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/cal-util/timeutil.c')
-rw-r--r--calendar/cal-util/timeutil.c501
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);
+}