diff options
author | Bruce Momjian <bruce@momjian.us> | 2006-11-24 15:26:18 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2006-11-24 15:26:18 +0000 |
commit | d2b694d825ce13bd87d6f76be040466de34f3787 (patch) | |
tree | 32e4e6beb47e7b2d7b68f39c5dd3fb438892f75c /src/backend/utils/adt/formatting.c | |
parent | 409600942b63e5303f65b38b16e7153f63f4a8be (diff) | |
download | postgresql-d2b694d825ce13bd87d6f76be040466de34f3787.tar.gz postgresql-d2b694d825ce13bd87d6f76be040466de34f3787.zip |
Fix to_char() locale handling to honor LC_TIME, not LC_MESSAGES.
Euler Taveira de Oliveira
Diffstat (limited to 'src/backend/utils/adt/formatting.c')
-rw-r--r-- | src/backend/utils/adt/formatting.c | 317 |
1 files changed, 135 insertions, 182 deletions
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index d97c1bf405a..93aad1a9015 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- * formatting.c * - * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.113 2006/10/04 00:29:59 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.114 2006/11/24 15:26:18 momjian Exp $ * * * Portions Copyright (c) 1999-2006, PostgreSQL Global Development Group @@ -73,7 +73,7 @@ #include <unistd.h> #include <math.h> #include <float.h> -#include <locale.h> +#include <time.h> #include "utils/builtins.h" #include "utils/date.h" @@ -83,8 +83,6 @@ #include "utils/numeric.h" #include "utils/pg_locale.h" -#define _(x) gettext((x)) - /* ---------- * Routines type * ---------- @@ -163,7 +161,6 @@ struct FormatNode /* ---------- * Full months - * This needs to be NLS-localized someday. * ---------- */ static char *months_full[] = { @@ -942,10 +939,6 @@ static NUMCacheEntry *NUM_cache_search(char *str); static NUMCacheEntry *NUM_cache_getnew(char *str); static void NUM_cache_remove(NUMCacheEntry *ent); -static char *localize_month_full(int index); -static char *localize_month(int index); -static char *localize_day_full(int index); -static char *localize_day(int index); /* ---------- * Fast sequential search, use index for data selection which @@ -2074,6 +2067,17 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, struct pg_tm *tm = NULL; TmFromChar *tmfc = NULL; TmToChar *tmtc = NULL; + char *save_loc = NULL; + + /* + * Set the LC_TIME only to do some operation (strftime) and then + * set it back. See pg_locale.c for explanations. + */ + if (S_TM(suf)) + { + save_loc = setlocale(LC_TIME, NULL); + setlocale(LC_TIME, locale_time); + } if (is_to_char) { @@ -2189,9 +2193,20 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) - strcpy(workbuff, localize_month_full(tm->tm_mon - 1)); + { + /* + * tm_mon in 'pg_tm struct' based on one, but rather POSIX 'tm struct' based on zero. + * See notes at the top of this file. + */ + tm->tm_mon = tm->tm_mon - 1; + strftime(workbuff, sizeof(workbuff), "%B", (struct tm *) tm); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { strcpy(workbuff, months_full[tm->tm_mon - 1]); + } sprintf(inout, "%*s", (S_FM(suf) || S_TM(suf)) ? 0 : -9, str_toupper(workbuff)); return strlen(p_inout); @@ -2200,9 +2215,22 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) - sprintf(inout, "%*s", 0, localize_month_full(tm->tm_mon - 1)); + { + /* + * tm_mon in 'pg_tm struct' based on one, but rather POSIX 'tm struct' based on zero. + * See notes at the top of this file. + */ + tm->tm_mon = tm->tm_mon - 1; + strftime(inout, 32, "%B", (struct tm *) tm); + /* capitalize output */ + inout[0] = pg_toupper((unsigned char) inout[0]); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]); + } return strlen(p_inout); case DCH_month: @@ -2210,9 +2238,20 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) - sprintf(inout, "%*s", 0, localize_month_full(tm->tm_mon - 1)); + { + /* + * tm_mon in 'pg_tm struct' based on one, but rather POSIX 'tm struct' based on zero. + * See notes at the top of this file. + */ + tm->tm_mon = tm->tm_mon - 1; + strftime(inout, 32, "%B", (struct tm *) tm); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]); + } *inout = pg_tolower((unsigned char) *inout); return strlen(p_inout); @@ -2221,9 +2260,20 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) - strcpy(inout, localize_month(tm->tm_mon - 1)); + { + /* + * tm_mon in 'pg_tm struct' based on one, but rather POSIX 'tm struct' based on zero. + * See notes at the top of this file. + */ + tm->tm_mon = tm->tm_mon - 1; + strftime(inout, 32, "%b", (struct tm *) tm); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { strcpy(inout, months[tm->tm_mon - 1]); + } str_toupper(inout); return strlen(p_inout); @@ -2232,9 +2282,22 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) - strcpy(inout, localize_month(tm->tm_mon - 1)); + { + /* + * tm_mon in 'pg_tm struct' based on one, but rather POSIX 'tm struct' based on zero. + * See notes at the top of this file. + */ + tm->tm_mon = tm->tm_mon - 1; + strftime(inout, 32, "%b", (struct tm *) tm); + /* capitalize output */ + inout[0] = pg_toupper((unsigned char) inout[0]); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { strcpy(inout, months[tm->tm_mon - 1]); + } return strlen(p_inout); case DCH_mon: @@ -2242,9 +2305,20 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) - strcpy(inout, localize_month(tm->tm_mon - 1)); + { + /* + * tm_mon in 'pg_tm struct' based on one, but rather POSIX 'tm struct' based on zero. + * See notes at the top of this file. + */ + tm->tm_mon = tm->tm_mon - 1; + strftime(inout, 32, "%b", (struct tm *) tm); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { strcpy(inout, months[tm->tm_mon - 1]); + } *inout = pg_tolower((unsigned char) *inout); return strlen(p_inout); @@ -2273,52 +2347,92 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, case DCH_DAY: INVALID_FOR_INTERVAL; if (S_TM(suf)) - strcpy(workbuff, localize_day_full(tm->tm_wday)); + { + strftime(workbuff, sizeof(workbuff), "%A", (struct tm *) tm); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { strcpy(workbuff, days[tm->tm_wday]); + } sprintf(inout, "%*s", (S_FM(suf) || S_TM(suf)) ? 0 : -9, str_toupper(workbuff)); return strlen(p_inout); case DCH_Day: INVALID_FOR_INTERVAL; if (S_TM(suf)) - sprintf(inout, "%*s", 0, localize_day_full(tm->tm_wday)); + { + strftime(inout, 32, "%A", (struct tm *) tm); + /* capitalize output */ + inout[0] = pg_toupper((unsigned char) inout[0]); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]); + } return strlen(p_inout); case DCH_day: INVALID_FOR_INTERVAL; if (S_TM(suf)) - sprintf(inout, "%*s", 0, localize_day_full(tm->tm_wday)); + { + strftime(inout, 32, "%A", (struct tm *) tm); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]); + } *inout = pg_tolower((unsigned char) *inout); return strlen(p_inout); case DCH_DY: INVALID_FOR_INTERVAL; if (S_TM(suf)) - strcpy(inout, localize_day(tm->tm_wday)); + { + strftime(inout, 32, "%a", (struct tm *) tm); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { strcpy(inout, days_short[tm->tm_wday]); + } str_toupper(inout); return strlen(p_inout); case DCH_Dy: INVALID_FOR_INTERVAL; if (S_TM(suf)) - strcpy(inout, localize_day(tm->tm_wday)); + { + strftime(inout, 32, "%a", (struct tm *) tm); + /* capitalize output */ + inout[0] = pg_toupper((unsigned char) inout[0]); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { strcpy(inout, days_short[tm->tm_wday]); + } return strlen(p_inout); case DCH_dy: INVALID_FOR_INTERVAL; if (S_TM(suf)) - strcpy(inout, localize_day(tm->tm_wday)); + { + strftime(inout, 32, "%a", (struct tm *) tm); + /* set it back; see comments in pg_locale.c */ + setlocale(LC_TIME, save_loc); + } else + { strcpy(inout, days_short[tm->tm_wday]); + } *inout = pg_tolower((unsigned char) *inout); return strlen(p_inout); @@ -2860,167 +2974,6 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval) return res; } -static char * -localize_month_full(int index) -{ - char *m = NULL; - - switch (index) - { - case 0: - m = _("January"); - break; - case 1: - m = _("February"); - break; - case 2: - m = _("March"); - break; - case 3: - m = _("April"); - break; - case 4: - m = _("May"); - break; - case 5: - m = _("June"); - break; - case 6: - m = _("July"); - break; - case 7: - m = _("August"); - break; - case 8: - m = _("September"); - break; - case 9: - m = _("October"); - break; - case 10: - m = _("November"); - break; - case 11: - m = _("December"); - break; - } - - return m; -} - -static char * -localize_month(int index) -{ - char *m = NULL; - - switch (index) - { - case 0: - m = _("Jan"); - break; - case 1: - m = _("Feb"); - break; - case 2: - m = _("Mar"); - break; - case 3: - m = _("Apr"); - break; - case 4: - m = _("May"); - break; - case 5: - m = _("Jun"); - break; - case 6: - m = _("Jul"); - break; - case 7: - m = _("Aug"); - break; - case 8: - m = _("Sep"); - break; - case 9: - m = _("Oct"); - break; - case 10: - m = _("Nov"); - break; - case 11: - m = _("Dec"); - break; - } - - return m; -} - -static char * -localize_day_full(int index) -{ - char *d = NULL; - - switch (index) - { - case 0: - d = _("Sunday"); - break; - case 1: - d = _("Monday"); - break; - case 2: - d = _("Tuesday"); - break; - case 3: - d = _("Wednesday"); - break; - case 4: - d = _("Thursday"); - break; - case 5: - d = _("Friday"); - break; - case 6: - d = _("Saturday"); - break; - } - - return d; -} - -static char * -localize_day(int index) -{ - char *d = NULL; - - switch (index) - { - case 0: - d = _("Sun"); - break; - case 1: - d = _("Mon"); - break; - case 2: - d = _("Tue"); - break; - case 3: - d = _("Wed"); - break; - case 4: - d = _("Thu"); - break; - case 5: - d = _("Fri"); - break; - case 6: - d = _("Sat"); - break; - } - - return d; -} /**************************************************************************** * Public routines |