summaryrefslogtreecommitdiffstats
path: root/panels/datetime/date-endian.c
diff options
context:
space:
mode:
Diffstat (limited to 'panels/datetime/date-endian.c')
-rw-r--r--panels/datetime/date-endian.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/panels/datetime/date-endian.c b/panels/datetime/date-endian.c
new file mode 100644
index 0000000..435a423
--- /dev/null
+++ b/panels/datetime/date-endian.c
@@ -0,0 +1,188 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Bastien Nocera <hadess@hadess.net>
+ *
+ */
+
+#include <errno.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <glib.h>
+#include <string.h>
+
+#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 ();
+ }
+}