Merge branch 'tz' into 'master'

gtimezone: fix parsing of Julian day in POSIX TZ format

Closes #1999

See merge request GNOME/glib!1314
This commit is contained in:
Philip Withnall 2020-01-15 17:57:16 +00:00
commit a711d59a2f
2 changed files with 75 additions and 17 deletions

View File

@ -1203,14 +1203,21 @@ parse_mwd_boundary (gchar **pos, TimeZoneDate *boundary)
return TRUE; return TRUE;
} }
/* Different implementations of tzset interpret the Julian day field /*
differently. For example, Linux specifies that it should be 1-based * This parses two slightly different ways of specifying
(1 Jan is JD 1) for both Jn and n formats, while zOS and BSD * the Julian day:
specify that a Jn JD is 1-based while an n JD is 0-based. Rather *
than trying to follow different specs, we will follow GDate's * - ignore_leap == TRUE
practice thatIn order to keep it simple, we will follow Linux's *
practice. */ * Jn This specifies the Julian day with n between 1 and 365. Leap days
* are not counted. In this format, February 29 can't be represented;
* February 28 is day 59, and March 1 is always day 60.
*
* - ignore_leap == FALSE
*
* n This specifies the zero-based Julian day with n between 0 and 365.
* February 29 is counted in leap years.
*/
static gboolean static gboolean
parse_julian_boundary (gchar** pos, TimeZoneDate *boundary, parse_julian_boundary (gchar** pos, TimeZoneDate *boundary,
gboolean ignore_leap) gboolean ignore_leap)
@ -1224,8 +1231,20 @@ parse_julian_boundary (gchar** pos, TimeZoneDate *boundary,
day += *(*pos)++ - '0'; day += *(*pos)++ - '0';
} }
if (ignore_leap)
{
if (day < 1 || 365 < day) if (day < 1 || 365 < day)
return FALSE; return FALSE;
if (day >= 59)
day++;
}
else
{
if (day < 0 || 365 < day)
return FALSE;
/* GDate wants day in range 1->366 */
day++;
}
g_date_clear (&date, 1); g_date_clear (&date, 1);
g_date_set_julian (&date, day); g_date_set_julian (&date, day);
@ -1234,9 +1253,6 @@ parse_julian_boundary (gchar** pos, TimeZoneDate *boundary,
boundary->mday = (int) g_date_get_day (&date); boundary->mday = (int) g_date_get_day (&date);
boundary->wday = 0; boundary->wday = 0;
if (!ignore_leap && day >= 59)
boundary->mday++;
return TRUE; return TRUE;
} }
@ -1258,13 +1274,13 @@ parse_tz_boundary (const gchar *identifier,
else if (*pos == 'J') else if (*pos == 'J')
{ {
++pos; ++pos;
if (!parse_julian_boundary (&pos, boundary, FALSE)) if (!parse_julian_boundary (&pos, boundary, TRUE))
return FALSE ; return FALSE ;
} }
/* Julian date which counts Feb 29 in leap years */ /* Julian date which counts Feb 29 in leap years */
else if (*pos >= '0' && '9' >= *pos) else if (*pos >= '0' && '9' >= *pos)
{ {
if (!parse_julian_boundary (&pos, boundary, TRUE)) if (!parse_julian_boundary (&pos, boundary, FALSE))
return FALSE; return FALSE;
} }
else else

View File

@ -2432,8 +2432,8 @@ test_posix_parse (void)
g_date_time_unref (gdt2); g_date_time_unref (gdt2);
g_time_zone_unref (tz); g_time_zone_unref (tz);
tz = g_time_zone_new ("NZST-12:00:00NZDT-13:00:00,280,77"); tz = g_time_zone_new ("NZST-12:00:00NZDT-13:00:00,279,76");
g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "NZST-12:00:00NZDT-13:00:00,280,77"); g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "NZST-12:00:00NZDT-13:00:00,279,76");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "NZST"); g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "NZST");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, 12 * 3600); g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, 12 * 3600);
g_assert (!g_time_zone_is_dst (tz, 0)); g_assert (!g_time_zone_is_dst (tz, 0));
@ -2533,6 +2533,48 @@ test_posix_parse (void)
g_date_time_unref (gdt1); g_date_time_unref (gdt1);
g_date_time_unref (gdt2); g_date_time_unref (gdt2);
g_time_zone_unref (tz); g_time_zone_unref (tz);
tz = g_time_zone_new ("VIR-00:30");
g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-00:30");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (30 * 60));
g_assert_false (g_time_zone_is_dst (tz, 0));
tz = g_time_zone_new ("VIR-00:30VID,0/00:00:00,365/23:59:59");
g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-00:30VID,0/00:00:00,365/23:59:59");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (30 * 60));
g_assert_false (g_time_zone_is_dst (tz, 0));
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "VID");
g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==, (90 * 60));
g_assert_true (g_time_zone_is_dst (tz, 1));
tz = g_time_zone_new ("VIR-02:30VID,0/00:00:00,365/23:59:59");
g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-02:30VID,0/00:00:00,365/23:59:59");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (150 * 60));
g_assert_false (g_time_zone_is_dst (tz, 0));
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "VID");
g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==, (210 * 60));
g_assert_true (g_time_zone_is_dst (tz, 1));
tz = g_time_zone_new ("VIR-02:30VID-04:30,0/00:00:00,365/23:59:59");
g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-02:30VID-04:30,0/00:00:00,365/23:59:59");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (150 * 60));
g_assert_false (g_time_zone_is_dst (tz, 0));
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "VID");
g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==, (270 * 60));
g_assert_true (g_time_zone_is_dst (tz, 1));
tz = g_time_zone_new ("VIR-12:00VID-13:00,0/00:00:00,365/23:59:59");
g_assert_cmpstr (g_time_zone_get_identifier (tz), ==, "VIR-12:00VID-13:00,0/00:00:00,365/23:59:59");
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "VIR");
g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, (720 * 60));
g_assert_false (g_time_zone_is_dst (tz, 0));
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "VID");
g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==, (780 * 60));
g_assert_true (g_time_zone_is_dst (tz, 1));
} }
static void static void