view: Fix daylight saving issue in week view
This patch fixes an issue when creating new events in week view the week after the daylight saving change. The problem was in the calc of the selected date, that's done couting the 30 minutes slots and adding that minutes to the week_start datetime. When there's a daylight saving change, the real date to select should be adjusted. This patch adds a new util function to make it easy to add minutes ignoring the tz so we can make this calc directly with gcal_date_time_add_floating_minutes. This also includes a new test file with some checks for the new util function and spring / autumn changes. This new function could be used in other places to fix specific issues that could be caused by the same logic error, calculate a selection or event position based on GDateTime operations. Fix https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/482
This commit is contained in:
committed by
Georges Basile Stavracas Neto
parent
ba08425fce
commit
6afb5cf3a5
@@ -294,8 +294,8 @@ on_click_gesture_released_cb (GtkGestureClick *click_gesture,
|
||||
|
||||
if (ltr)
|
||||
{
|
||||
start = g_date_time_add_minutes (week_start, start_cell * 30);
|
||||
end = g_date_time_add_minutes (week_start, (end_cell + 1) * 30);
|
||||
start = gcal_date_time_add_floating_minutes (week_start, start_cell * 30);
|
||||
end = gcal_date_time_add_floating_minutes (week_start, (end_cell + 1) * 30);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -306,8 +306,8 @@ on_click_gesture_released_cb (GtkGestureClick *click_gesture,
|
||||
rtl_start_cell = start_cell + (rtl_column - column) * 48;
|
||||
rtl_end_cell = (rtl_column * MINUTES_PER_DAY + minute) / 30;
|
||||
|
||||
start = g_date_time_add_minutes (week_start, rtl_start_cell * 30);
|
||||
end = g_date_time_add_minutes (week_start, (rtl_end_cell + 1) * 30);
|
||||
start = gcal_date_time_add_floating_minutes (week_start, rtl_start_cell * 30);
|
||||
end = gcal_date_time_add_floating_minutes (week_start, (rtl_end_cell + 1) * 30);
|
||||
}
|
||||
|
||||
local_x = round ((column + 0.5) * (alloc.width / 7.0));
|
||||
|
||||
@@ -258,3 +258,31 @@ gcal_timezone_to_icaltimezone (GTimeZone *tz)
|
||||
return ical_tz;
|
||||
}
|
||||
|
||||
/**
|
||||
* gcal_date_time_add_floating_minutes:
|
||||
* @initial: Initial #GDateTime to add minutes
|
||||
* @minutes: The number of minutes to add
|
||||
*
|
||||
* Calculate the datetime initial + minutes without caring about dayligh saving
|
||||
* changes, so if it's 02:30 + 30 minutes, the result will be 03:00, always,
|
||||
* independently of the daylight saving logic.
|
||||
*
|
||||
* Returns: (transfer full): A new #GDateTime with initial + minutes
|
||||
*/
|
||||
GDateTime*
|
||||
gcal_date_time_add_floating_minutes (GDateTime *initial,
|
||||
gint minutes)
|
||||
{
|
||||
g_autoptr (GDateTime) result = NULL;
|
||||
GTimeSpan initial_offset = 0;
|
||||
GTimeSpan result_offset = 0;
|
||||
GTimeSpan offset = 0;
|
||||
|
||||
result = g_date_time_add_minutes (initial, minutes);
|
||||
initial_offset = g_date_time_get_utc_offset (initial);
|
||||
result_offset = g_date_time_get_utc_offset (result);
|
||||
offset = initial_offset - result_offset;
|
||||
// offset is in microseconds, convert to seconds
|
||||
offset = offset / 1000000;
|
||||
return g_date_time_add_seconds (result, offset);
|
||||
}
|
||||
|
||||
@@ -53,4 +53,8 @@ GDateTime* gcal_date_time_from_icaltime (const ICalTime
|
||||
|
||||
ICalTimezone* gcal_timezone_to_icaltimezone (GTimeZone *tz);
|
||||
|
||||
|
||||
GDateTime* gcal_date_time_add_floating_minutes (GDateTime *initial,
|
||||
gint minutes);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -33,6 +33,7 @@ libgcal_test_dep = declare_dependency(
|
||||
|
||||
tests = [
|
||||
'server',
|
||||
'daylight-saving',
|
||||
'discoverer',
|
||||
'event',
|
||||
'range',
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/* test-daylight-saving.c
|
||||
*
|
||||
* Copyright © 2023 Daniel García Moreno <daniel.garcia@suse.com>
|
||||
*
|
||||
* 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 3 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/>.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include "gcal-utils.h"
|
||||
|
||||
/*********************************************************************************************************************/
|
||||
|
||||
static void
|
||||
floating_minutes (void)
|
||||
{
|
||||
g_autoptr (GDateTime) week_start = NULL;
|
||||
g_autoptr (GDateTime) start = NULL;
|
||||
g_autoptr (GDateTime) end = NULL;
|
||||
g_autoptr (GTimeZone) cest = NULL;
|
||||
|
||||
int start_cell = 3 * 2; // three hours (daylight time starts at 3:00 AM)
|
||||
int end_cell = start_cell;
|
||||
|
||||
g_test_bug ("482");
|
||||
|
||||
cest = g_time_zone_new_identifier ("Europe/Madrid");
|
||||
|
||||
// Without daylight saving change
|
||||
week_start = g_date_time_new (cest, 2023, 11, 5, 0, 0, 0);
|
||||
g_assert_cmpstr (g_date_time_format_iso8601 (week_start), ==, "2023-11-05T00:00:00+01");
|
||||
g_assert_false (g_date_time_is_daylight_savings (week_start));
|
||||
|
||||
start = gcal_date_time_add_floating_minutes (week_start, start_cell * 30);
|
||||
end = gcal_date_time_add_floating_minutes (week_start, (end_cell + 1) * 30);
|
||||
|
||||
g_assert_false (g_date_time_is_daylight_savings (start));
|
||||
g_assert_false (g_date_time_is_daylight_savings (end));
|
||||
|
||||
g_assert_cmpstr (g_date_time_format_iso8601 (start), ==, "2023-11-05T03:00:00+01");
|
||||
g_assert_cmpstr (g_date_time_format_iso8601 (end), ==, "2023-11-05T03:30:00+01");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
floating_minutes_october (void)
|
||||
{
|
||||
g_autoptr (GDateTime) week_start = NULL;
|
||||
g_autoptr (GDateTime) start = NULL;
|
||||
g_autoptr (GDateTime) end = NULL;
|
||||
g_autoptr (GTimeZone) cest = NULL;
|
||||
|
||||
int start_cell = 3 * 2; // three hours (daylight time starts at 3:00 AM)
|
||||
int end_cell = start_cell;
|
||||
|
||||
g_test_bug ("482");
|
||||
|
||||
cest = g_time_zone_new_identifier ("Europe/Madrid");
|
||||
|
||||
// With daylight saving change
|
||||
week_start = g_date_time_new (cest, 2023, 10, 29, 0, 0, 0);
|
||||
g_assert_cmpstr (g_date_time_format_iso8601 (week_start), ==, "2023-10-29T00:00:00+02");
|
||||
g_assert_true (g_date_time_is_daylight_savings (week_start));
|
||||
|
||||
start = gcal_date_time_add_floating_minutes (week_start, start_cell * 30);
|
||||
end = gcal_date_time_add_floating_minutes (week_start, (end_cell + 1) * 30);
|
||||
|
||||
g_assert_cmpstr (g_date_time_format_iso8601 (start), ==, "2023-10-29T03:00:00+01");
|
||||
g_assert_cmpstr (g_date_time_format_iso8601 (end), ==, "2023-10-29T03:30:00+01");
|
||||
}
|
||||
|
||||
static void
|
||||
floating_minutes_march (void)
|
||||
{
|
||||
g_autoptr (GDateTime) week_start = NULL;
|
||||
g_autoptr (GDateTime) start = NULL;
|
||||
g_autoptr (GDateTime) end = NULL;
|
||||
g_autoptr (GTimeZone) cest = NULL;
|
||||
|
||||
int start_cell = 3 * 2; // three hours (daylight time starts at 3:00 AM)
|
||||
int end_cell = start_cell;
|
||||
|
||||
g_test_bug ("482");
|
||||
|
||||
cest = g_time_zone_new_identifier ("Europe/Madrid");
|
||||
|
||||
// With daylight saving change
|
||||
week_start = g_date_time_new (cest, 2023, 3, 26, 0, 0, 0);
|
||||
g_assert_cmpstr (g_date_time_format_iso8601 (week_start), ==, "2023-03-26T00:00:00+01");
|
||||
g_assert_false (g_date_time_is_daylight_savings (week_start));
|
||||
|
||||
start = gcal_date_time_add_floating_minutes (week_start, start_cell * 30);
|
||||
end = gcal_date_time_add_floating_minutes (week_start, (end_cell + 1) * 30);
|
||||
|
||||
g_assert_cmpstr (g_date_time_format_iso8601 (start), ==, "2023-03-26T03:00:00+02");
|
||||
g_assert_cmpstr (g_date_time_format_iso8601 (end), ==, "2023-03-26T03:30:00+02");
|
||||
}
|
||||
|
||||
/*********************************************************************************************************************/
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_setenv ("TZ", "UTC", TRUE);
|
||||
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_bug_base ("https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/");
|
||||
|
||||
g_test_add_func ("/daylight/floating-minutes", floating_minutes);
|
||||
g_test_add_func ("/daylight/floating-minutes-october", floating_minutes_october);
|
||||
g_test_add_func ("/daylight/floating-minutes-march", floating_minutes_march);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
Reference in New Issue
Block a user