gnome-control-center/panels/datetime/date-endian.c
Mathieu Bridon 623abfb428 datetime: Fix date endianess for en_HK
Hong Kong people expect to use a little endian date in English. (and a
big endian date in Chinese)

The D_FMT format string for en_HK is '%A, %B %d, %Y', which the current
code parses as middle endian.

This commit makes the code parse it as little endian, that is it doesn't
ignore the %A formatter any more.

en_HK is the only UTF-8 locale with this D_FMT format string, so this
shouldn't change anything for other locales.

https://bugzilla.gnome.org/show_bug.cgi?id=750781
2015-06-15 17:27:34 +02:00

177 lines
3.7 KiB
C

/*
* 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 <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)
{
const char *old_lang;
DateEndianess endian;
old_lang = setlocale (LC_TIME, lang);
endian = date_endian_get_default (verbose);
setlocale (LC_TIME, old_lang);
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 ();
}
}