/* * Copyright (C) 2011 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Author: Bastien Nocera * */ #include #include #include #include #include #include "date-endian.h" /* We default to returning DATE_ENDIANESS_LITTLE because that's * what 3.4 billion people use */ #define DEFAULT_ENDIANESS DATE_ENDIANESS_LITTLE typedef enum { ITEM_NONE = 0, ITEM_DAY, ITEM_MONTH, ITEM_YEAR } Item; static gboolean has_item (Item *items, Item item) { guint i; for (i = 0; i < 3; i++) { if (items[i] == ITEM_NONE) return FALSE; if (items[i] == item) return TRUE; } return FALSE; } DateEndianess date_endian_get_default (gboolean verbose) { const char *fmt; const char *p; Item items[3]; guint i; fmt = nl_langinfo (D_FMT); g_return_val_if_fail (fmt != NULL, DEFAULT_ENDIANESS); if (verbose) g_print ("%s", fmt); if (g_str_equal (fmt, "%F")) return DATE_ENDIANESS_BIG; i = 0; memset (&items, 0, sizeof(items)); /* Assume ASCII only */ for (p = fmt; *p != '\0'; p++) { char c; /* Look for '%' */ if (*p != '%') continue; /* Only assert when we're sure we don't have another '%' */ if (i >= 4) { g_warning ("Could not parse format '%s', too many formats", fmt); return DEFAULT_ENDIANESS; } c = *(p + 1); /* Ignore alternative formats */ if (c == 'O' || c == '-' || c == 'E') c = *(p + 2); if (c == '\0') { g_warning ("Count not parse format '%s', unterminated '%%'", fmt); return DEFAULT_ENDIANESS; } switch (c) { case 'A': case 'd': case 'e': if (has_item (items, ITEM_DAY) == FALSE) { items[i] = ITEM_DAY; i++; } break; case 'm': case 'b': case 'B': if (has_item (items, ITEM_MONTH) == FALSE) { items[i] = ITEM_MONTH; i++; } break; case 'y': case 'Y': if (has_item (items, ITEM_YEAR) == FALSE) { items[i] = ITEM_YEAR; i++; } break; case 'a': /* Ignore */ ; } } if (items[0] == ITEM_DAY && items[1] == ITEM_MONTH && items[2] == ITEM_YEAR) return DATE_ENDIANESS_LITTLE; if (items[0] == ITEM_YEAR && items[1] == ITEM_MONTH && items[2] == ITEM_DAY) return DATE_ENDIANESS_BIG; if (items[0] == ITEM_MONTH && items[1] == ITEM_DAY && items[2] == ITEM_YEAR) return DATE_ENDIANESS_MIDDLE; if (items[0] == ITEM_YEAR && items[1] == ITEM_DAY && items[2] == ITEM_MONTH) return DATE_ENDIANESS_YDM; g_warning ("Could not parse format '%s'", fmt); return DEFAULT_ENDIANESS; } DateEndianess date_endian_get_for_lang (const char *lang, gboolean verbose) { locale_t locale; locale_t old_locale; DateEndianess endian; locale = newlocale (LC_TIME_MASK, lang, (locale_t) 0); if (locale == (locale_t) 0) g_warning ("Failed to create locale %s: %s", lang, g_strerror (errno)); else old_locale = uselocale (locale); endian = date_endian_get_default (verbose); if (locale != (locale_t) 0) { uselocale (old_locale); freelocale (locale); } return endian; } const char * date_endian_to_string (DateEndianess endianess) { switch (endianess) { case DATE_ENDIANESS_LITTLE: return "Little (DD-MM-YYYY)"; case DATE_ENDIANESS_BIG: return "Big (YYYY-MM-DD)"; case DATE_ENDIANESS_MIDDLE: return "Middle (MM-DD-YYYY)"; case DATE_ENDIANESS_YDM: return "YDM (YYYY-DD-MM)"; default: g_assert_not_reached (); } }