From 09d11d36c33f931e1766f5d02dffddcc5d0cbb30 Mon Sep 17 00:00:00 2001 From: dfs Date: Sun, 8 Jul 2007 16:57:47 +0000 Subject: [PATCH] Added tzconvert function. --- src/custom.h | 2 +- src/err.h | 6 ++- src/funcs.c | 109 +++++++++++++++++++++++++++++++++++++++++++- src/langs/finnish.h | 12 +++-- src/langs/french.h | 8 ++-- src/langs/polish.h | 8 ++-- src/langs/portbr.h | 5 +- 7 files changed, 134 insertions(+), 16 deletions(-) diff --git a/src/custom.h b/src/custom.h index 08bf10ce..a1a164b6 100644 --- a/src/custom.h +++ b/src/custom.h @@ -11,7 +11,7 @@ /* */ /***************************************************************/ -/* $Id: custom.h,v 1.37 2007-07-01 14:49:47 dfs Exp $ */ +/* $Id: custom.h,v 1.38 2007-07-08 16:57:47 dfs Exp $ */ /*---------------------------------------------------------------------*/ /* LAT_DEG, LAT_MIN and LAT_SEC: Latitude of your location */ diff --git a/src/err.h b/src/err.h index a8ab5ec6..d5a39026 100644 --- a/src/err.h +++ b/src/err.h @@ -10,7 +10,7 @@ /* */ /***************************************************************/ -/* $Id: err.h,v 1.4 2000-02-18 03:45:51 dfs Exp $ */ +/* $Id: err.h,v 1.5 2007-07-08 16:57:47 dfs Exp $ */ /* Note that not all of the "errors" are really errors - some are just messages for information purposes. Constants beginning with M_ should @@ -118,6 +118,7 @@ #define M_QUEUED 96 #define E_EXPECTING_NUMBER 97 #define M_BAD_WARN_FUNC 98 +#define E_CANT_CONVERT_TZ 99 #ifdef MK_GLOBALS #undef EXTERN @@ -230,7 +231,8 @@ EXTERN char *ErrMsg[] "No reminders.", "%d reminder(s) queued for later today.\n", "Expecting number", - "Bad function in WARN clause" + "Bad function in WARN clause", + "Can't convert between time zones" } #endif /* MK_GLOBALS */ ; diff --git a/src/funcs.c b/src/funcs.c index 052ce31b..8ecf4320 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -12,7 +12,7 @@ /***************************************************************/ #include "config.h" -static char const RCSID[] = "$Id: funcs.c,v 1.14 2007-06-29 01:52:36 dfs Exp $"; +static char const RCSID[] = "$Id: funcs.c,v 1.15 2007-07-08 16:57:47 dfs Exp $"; #include @@ -127,6 +127,7 @@ static int FRealnow (void); static int FRealtoday (void); static int FToday (void); static int FTrigger (void); +static int FTzconvert (void); static int CheckArgs (Operator *f, int nargs); static int CleanUpAfterFunc (void); static int SunStuff (int rise, double cosz, int jul); @@ -252,6 +253,7 @@ Operator Func[] = { { "trigtime", 0, 0, FTrigtime }, { "trigvalid", 0, 0, FTrigvalid }, { "typeof", 1, 1, FTypeof }, + { "tzconvert", 2, 3, FTzconvert }, { "upper", 1, 1, FUpper }, { "value", 1, 2, FValue }, { "version", 0, 0, FVersion }, @@ -2285,3 +2287,108 @@ static int FDatepart(void) RetVal.v.val = DATEPART(ARG(0)); return OK; } + +/***************************************************************/ +/* */ +/* FTz */ +/* */ +/* Conversion between different timezones. */ +/* */ +/***************************************************************/ +static int tz_set_tz(char const *tz) +{ + int r; + if (tz == NULL) { + r = unsetenv("TZ"); + } else { + r = setenv("TZ", tz, 1); + } + tzset(); + return r; +} + +static int tz_convert(int year, int month, int day, + int hour, int minute, + char const *src_tz, char const *tgt_tz, + struct tm *tm) +{ + int r; + time_t t; + struct tm *res; + char *old_tz; + + /* init tm struct */ + tm->tm_sec = 0; + tm->tm_min = minute; + tm->tm_hour = hour; + tm->tm_mday = day; + tm->tm_mon = month; + tm->tm_year = year - 1900; + tm->tm_wday = 0; /* ignored by mktime */ + tm->tm_yday = 0; /* ignored by mktime */ + tm->tm_isdst = -1; /* information not available */ + + /* backup old TZ env var */ + old_tz = getenv("TZ"); + if (tgt_tz == NULL) { + tgt_tz = old_tz; + } + + /* set source TZ */ + r = tz_set_tz(src_tz); + if (r == -1) { + return -1; + } + + /* create timestamp in UTC */ + t = mktime(tm); + + /* set target TZ */ + r = tz_set_tz(tgt_tz); + if (r == -1) { + tz_set_tz(old_tz); + return -1; + } + + /* convert to target TZ */ + res = localtime_r(&t, tm); + + /* restore old TZ */ + tz_set_tz(old_tz); + + /* return result */ + if (res == NULL) { + return -1; + } else { + return 1; + } +} + +static int FTzconvert(void) +{ + int year, month, day, hour, minute, r; + int jul, tim; + struct tm tm; + if (ARG(0).type != DATETIME_TYPE || + ARG(1).type != STR_TYPE) return E_BAD_TYPE; + if (Nargs == 3 && ARG(2).type != STR_TYPE) return E_BAD_TYPE; + + FromJulian(DATEPART(ARG(0)), &year, &month, &day); + r = TIMEPART(ARG(0)); + hour = r / 60; + minute = r % 60; + if (Nargs == 2) { + r = tz_convert(year, month, day, hour, minute, ARG(1).v.str, NULL, + &tm); + } else { + r = tz_convert(year, month, day, hour, minute, + ARG(1).v.str, ARG(2).v.str, + &tm); + } + if (r == -1) return E_CANT_CONVERT_TZ; + jul = Julian(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday); + tim = tm.tm_hour * 60 + tm.tm_min; + RetVal.type = DATETIME_TYPE; + RetVal.v.val = jul * MINUTES_PER_DAY + tim; + return OK; +} diff --git a/src/langs/finnish.h b/src/langs/finnish.h index 238731b2..590efdf3 100644 --- a/src/langs/finnish.h +++ b/src/langs/finnish.h @@ -16,7 +16,7 @@ /* */ /***************************************************************/ -/* $Id: finnish.h,v 1.12 2007-07-03 03:42:46 dfs Exp $ */ +/* $Id: finnish.h,v 1.13 2007-07-08 16:57:49 dfs Exp $ */ /* The very first define in a language support file must be L_LANGNAME: */ #define L_LANGNAME "Finnish" @@ -308,7 +308,8 @@ EXTERN char *ErrMsg[] = "Ei viestej\xE4.", "%d viesti(\xE4) t\xE4m\xE4n p\xE4iv\xE4n jonossa.\n", "Numero puuttuu", - "Virheellinen funktio WARN-lausekkeessa" + "Virheellinen funktio WARN-lausekkeessa", + "Can't convert between time zones" #elif IBMEXTENDED "Ok", @@ -409,7 +410,8 @@ EXTERN char *ErrMsg[] = "Ei viestej\x84.", "%d viesti(\x84) t\x84m\x84n p\x84iv\x84n jonossa.\n", "Numero puuttuu" - "Virheellinen funktio WARN-lausekkeessa" + "Virheellinen funktio WARN-lausekkeessa", + "Can't convert between time zones" #else "Ok", "Puuttuva ']'", @@ -509,7 +511,9 @@ EXTERN char *ErrMsg[] = "Ei viestej{.", "%d viesti({) t{m{n p{iv{n jonossa.\n", "Numero puuttuu", - "Virheellinen funktio WARN-lausekkeessa" + "Virheellinen funktio WARN-lausekkeessa", + "Can't convert between time zones" + #endif }; #endif /* MK_GLOBALS */ diff --git a/src/langs/french.h b/src/langs/french.h index 7af172c5..aa0dfa82 100644 --- a/src/langs/french.h +++ b/src/langs/french.h @@ -15,7 +15,7 @@ /* */ /***************************************************************/ -/* $Id: french.h,v 1.10 2007-07-03 03:42:46 dfs Exp $ */ +/* $Id: french.h,v 1.11 2007-07-08 16:57:49 dfs Exp $ */ /* The very first define in a language support file must be L_LANGNAME: */ #define L_LANGNAME "French" @@ -245,7 +245,8 @@ EXTERN char *ErrMsg[] = "Pas de rappels.", "%d rappel(s) en file pour aujourd'hui.\n", "Nombre attendu", - "Fonction ill\351gale apr\350s WARN" + "Fonction ill\351gale apr\350s WARN", + "Can't convert between time zones" #else /* ISOLATIN1 */ "Ok", "']' manquant", @@ -345,7 +346,8 @@ EXTERN char *ErrMsg[] = "Pas de rappels.", "%d rappel(s) en file pour aujourd'hui.\n", "Nombre attendu", - "Fonction illegale apres WARN" + "Fonction illegale apres WARN", + "Can't convert between time zones" #endif /* ISOLATIN1 */ }; #endif /* MK_GLOBALS */ diff --git a/src/langs/polish.h b/src/langs/polish.h index 0d918829..4c1a9b2e 100644 --- a/src/langs/polish.h +++ b/src/langs/polish.h @@ -14,7 +14,7 @@ /* */ /***************************************************************/ -/* $Id: polish.h,v 1.10 2007-07-03 03:42:46 dfs Exp $ */ +/* $Id: polish.h,v 1.11 2007-07-08 16:57:49 dfs Exp $ */ /* The very first define in a language support file must be L_LANGNAME: */ #define L_LANGNAME "Polish" @@ -280,7 +280,8 @@ EXTERN char *ErrMsg[] = "Brak przypomnie\361.", "%d Przypomnienia zakolejkowane na p\363\274niej.\n", "Spodziewana liczba", - "Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)" + "Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)", + "Can't convert between time zones" #else /* ISOLATIN1 */ "OK", "Brakujacy ']'", @@ -380,7 +381,8 @@ EXTERN char *ErrMsg[] = "Brak przypomnien.", "%d Przypomnienia zakolejkowane na pozniej.\n", "Spodziewana liczba", - "Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)" + "Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)", + "Can't convert between time zones" #endif /* ISOLATIN1 */ }; #endif /* MK_GLOBALS */ diff --git a/src/langs/portbr.h b/src/langs/portbr.h index 232e04a9..06e54f78 100644 --- a/src/langs/portbr.h +++ b/src/langs/portbr.h @@ -15,7 +15,7 @@ /* */ /***************************************************************/ -/* $Id: portbr.h,v 1.9 2007-07-03 03:42:46 dfs Exp $ */ +/* $Id: portbr.h,v 1.10 2007-07-08 16:57:49 dfs Exp $ */ /* The very first define in a language support file must be L_LANGNAME: */ #define L_LANGNAME "Brazilian Portuguese" @@ -246,7 +246,8 @@ EXTERN char *ErrMsg[] = "Sem compromissos.", "%d compromisso(s) colocados na fila para mais tarde.\n", "Esperando numero", - "Funcao ilegal na clausula WARN" + "Funcao ilegal na clausula WARN", + "Can't convert between time zones" }; #endif /* MK_GLOBALS */