diff --git a/src/core/gcal-context.c b/src/core/gcal-context.c index 9c450240..48bfed20 100644 --- a/src/core/gcal-context.c +++ b/src/core/gcal-context.c @@ -116,7 +116,7 @@ set_week_start_day_from_variant (GcalContext *self, /* find the actual 'default' from locale */ if (weekday->value == G_DESKTOP_WEEKDAY_DEFAULT) - weekday = g_enum_get_value (g_type_class_get (G_DESKTOP_TYPE_WEEKDAY), gcal_util_get_first_weekday ()); + weekday = g_enum_get_value (g_type_class_get (G_DESKTOP_TYPE_WEEKDAY), gcal_util_get_first_weekday_iso ()); if (self->week_start_day == weekday->value) return; @@ -391,7 +391,7 @@ gcal_context_class_init (GcalContextClass *klass) properties[PROP_WEEK_START_DAY] = g_param_spec_enum ("week-start-day", NULL, NULL, - G_DESKTOP_TYPE_WEEKDAY, gcal_util_get_first_weekday (), + G_DESKTOP_TYPE_WEEKDAY, gcal_util_get_first_weekday_iso (), G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, properties); @@ -535,7 +535,7 @@ gcal_context_get_time_format (GcalContext *self) GDesktopWeekday gcal_context_get_week_start_day (GcalContext *self) { - g_return_val_if_fail (GCAL_IS_CONTEXT (self), gcal_util_get_first_weekday ()); + g_return_val_if_fail (GCAL_IS_CONTEXT (self), gcal_util_get_first_weekday_iso ()); return self->week_start_day; } diff --git a/src/gui/common/gcal-date-chooser.c b/src/gui/common/gcal-date-chooser.c index e23fdd29..9cc83ed2 100644 --- a/src/gui/common/gcal-date-chooser.c +++ b/src/gui/common/gcal-date-chooser.c @@ -1083,7 +1083,7 @@ gcal_date_chooser_init (GcalDateChooser *self) self->date = g_date_time_new_now_local (); g_date_time_get_ymd (self->date, &self->this_year, NULL, NULL); - self->week_start = gcal_util_get_first_weekday (); + self->week_start = gcal_util_get_first_weekday_iso (); gtk_widget_init_template (GTK_WIDGET (self)); diff --git a/src/gui/views/gcal-month-view.c b/src/gui/views/gcal-month-view.c index d3b47939..e5868c07 100644 --- a/src/gui/views/gcal-month-view.c +++ b/src/gui/views/gcal-month-view.c @@ -194,7 +194,7 @@ allocate_overflow_popover (GcalMonthView *self, static inline void update_weekday_labels (GcalMonthView *self) { - const gint first_weekday = gcal_util_get_first_weekday (); + const gint first_weekday = gcal_util_get_first_weekday_iso (); for (gint i = 0; i < GCAL_N_WEEKDAYS; i++) { diff --git a/src/gui/views/gcal-week-header.c b/src/gui/views/gcal-week-header.c index de1e926a..133a84e5 100644 --- a/src/gui/views/gcal-week-header.c +++ b/src/gui/views/gcal-week-header.c @@ -100,8 +100,6 @@ struct _GcalWeekHeader GtkWidget *overflow_label[GCAL_N_WEEKDAYS]; WeekdayHeader weekday_header[GCAL_N_WEEKDAYS]; - gint first_weekday; - /* * Used for checking if the header is in collapsed state or expand state * false is collapse state true is expand state @@ -1762,8 +1760,6 @@ gcal_week_header_init (GcalWeekHeader *self) gtk_widget_set_visible (self->dnd.widget, FALSE); gtk_widget_set_parent (self->dnd.widget, GTK_WIDGET (self)); - self->first_weekday = gcal_util_get_first_weekday (); - gtk_widget_init_template (GTK_WIDGET (self)); for (i = 0; i < GCAL_N_WEEKDAYS; i++) diff --git a/src/utils/gcal-date-time-utils.c b/src/utils/gcal-date-time-utils.c index d263272a..202aecf3 100644 --- a/src/utils/gcal-date-time-utils.c +++ b/src/utils/gcal-date-time-utils.c @@ -83,7 +83,7 @@ gcal_date_time_get_start_of_week (GDateTime *date) g_assert (date != NULL); - first_weekday = gcal_util_get_first_weekday (); + first_weekday = gcal_util_get_first_weekday_iso (); weekday = g_date_time_get_day_of_week (date) % GCAL_N_WEEKDAYS; n_days_after_week_start = (GCAL_N_WEEKDAYS + weekday - first_weekday) % GCAL_N_WEEKDAYS; diff --git a/src/utils/gcal-utils.c b/src/utils/gcal-utils.c index 7410317c..0b3aa9bb 100644 --- a/src/utils/gcal-utils.c +++ b/src/utils/gcal-utils.c @@ -213,36 +213,46 @@ gcal_util_get_desc_from_component (ECalComponent *component, /** * gcal_util_get_first_weekday: * - * Copied from Clocks, which by itself is - * copied from GtkCalendar. + * Finds the locale default first day of week + * respecting the ISO day counting (Monday: 1 - Sunday: 7). * - * Returns: the first weekday, from 0 to 6 + * Prefer using `GcalContext:week-start-day` property or + * the `GcalContext:gcal_context_get_week_start_day()` method + * to get the current setting from gsettings-desktop-schemas. + * Use this utility method only as a fallback. + * + * Returns: the first weekday, from 1 to 7 */ gint -gcal_util_get_first_weekday (void) +gcal_util_get_first_weekday_iso (void) { gint week_start; #ifdef HAVE__NL_TIME_FIRST_WEEKDAY - union { unsigned int word; char *string; } langinfo; - gint week_1stday = 0; + union { unsigned int baseline; char *offset; } langinfo; + gint iso_week_base = 7; /* default to Sunday (19971130) */ gint first_weekday = 1; guint week_origin; - langinfo.string = nl_langinfo (_NL_TIME_FIRST_WEEKDAY); - first_weekday = langinfo.string[0]; - langinfo.string = nl_langinfo (_NL_TIME_WEEK_1STDAY); - week_origin = langinfo.word; + /* first day of week index */ + langinfo.offset = nl_langinfo (_NL_TIME_FIRST_WEEKDAY); + first_weekday = langinfo.offset[0]; + + /* find the baseline week origin */ + langinfo.offset = nl_langinfo (_NL_TIME_WEEK_1STDAY); + week_origin = langinfo.baseline; + if (week_origin == 19971130) /* Sunday */ - week_1stday = 0; + iso_week_base = 7; else if (week_origin == 19971201) /* Monday */ - week_1stday = 1; + iso_week_base = 1; + else if (week_origin == 19971129) /* unusual: Saturday */ + iso_week_base = 6; else g_warning ("Unknown value of _NL_TIME_WEEK_1STDAY.\n"); - week_start = (week_1stday + first_weekday - 1) % GCAL_N_WEEKDAYS; - + week_start = ((iso_week_base - 1 + (first_weekday - 1)) % GCAL_N_WEEKDAYS) + 1; #else gchar *gtk_week_start; diff --git a/src/utils/gcal-utils.h b/src/utils/gcal-utils.h index faf6caac..4b8702f2 100644 --- a/src/utils/gcal-utils.h +++ b/src/utils/gcal-utils.h @@ -63,7 +63,7 @@ GdkPaintable* gcal_util_get_circle_paintable_from_color (const GdkRGBA gchar* gcal_util_get_desc_from_component (ECalComponent *component, const gchar *joint_char); -gint gcal_util_get_first_weekday (void); +gint gcal_util_get_first_weekday_iso (void); ECalComponent* gcal_util_build_component_from_details (const gchar *summary, GDateTime *initial_date, diff --git a/tests/test-utils.c b/tests/test-utils.c index bec3008b..947189b6 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -17,6 +17,7 @@ */ #include +#include #include "gcal-utils.h" @@ -191,6 +192,47 @@ extract_meeting_url (void) /*********************************************************************************************************************/ +typedef struct { + const char *locale_name; + int week_start_index; +} LocaleIsoWeekDay; + +static void +test_first_weekday (void) +{ + LocaleIsoWeekDay test_cases[] = { + { "C", 7 }, // Baseline standard (Sunday) + { "en_US.UTF-8", 7 }, // US Standard (Sunday) + { "de_DE.UTF-8", 1 }, // Euro Standard (Monday) + { "en_GB.UTF-8", 1 }, // UK Standard (Monday) + { "fa_IR.UTF-8", 6 } // Iran, Somalia, Afghanistan (Saturday) + }; + + const char* initial_locale = setlocale (LC_ALL, NULL); + + for (size_t i = 0; i < G_N_ELEMENTS (test_cases); ++i) + { + LocaleIsoWeekDay testcase = test_cases[i]; + char *current_locale = setlocale (LC_ALL, testcase.locale_name); + + if (!current_locale) + { + g_message ("Locale %s not installed. Skipping", testcase.locale_name); + continue; + } + else + { + g_message ("Testing locale %s", testcase.locale_name); + g_assert_cmpint (testcase.week_start_index, ==, gcal_util_get_first_weekday_iso ()); + } + } + + /* restore locale */ + setlocale (LC_ALL, initial_locale); +} + +/*********************************************************************************************************************/ + gint main (gint argc, gchar *argv[]) @@ -202,6 +244,7 @@ main (gint argc, g_test_add_func ("/utils/date-time/date_time_from_icaltime", date_time_from_icaltime); g_test_add_func ("/utils/misc/extract_meeting_url", extract_meeting_url); + g_test_add_func ("/utils/misc/get_first_weekday", test_first_weekday); return g_test_run (); }