Tuesday, November 05, 2024

Re: timezone Etc/GMT+1

On 2024-11-05, Eric Grosse <grosse@gmail.com> wrote:
> There was a sign change in /usr/share/zoneinfo/Etc/GMT[+-]* last
> month. (The Go builder test harness noticed and I confirmed.) Anyone
> here know if that was an intended change?
>
> After some quick search, I'm not regarding it as a bug; StackOverflow
> has background on the sign ambiguity between POSIX and ISO 8601, and
> that upstream timezone database suppliers have inconsistent sign
> conventions for east / west of GMT. Anyway, the Go team has put in a
> special exception for OpenBSD so you shouldn't be affected by their
> test. I'm just curious; didn't spot it in release notes or mailing
> lists.

I suspect this may relate to this change:

---------------------
PatchSet 37
Date: 2024/09/18 18:05:50
Author: millert
Branch: HEAD
Tag: OPENBSD_7_6_BASE
Log:
zic: cherrypick support for %z in time zone formats

This extends the zic input format to add support for %z, which
expands to a UTC offset in as-short-as-possible ISO 8601 format.
It's intended to better support zones that do not have an established
abbreviation already. tzdata2024b and higher require a version of
zic that supports the %z format. From upstream tzcode. OK beck@

Members:
zic.8:1.5->1.6
zic.c:1.26->1.27

Index: src/usr.sbin/zic/zic.8
diff -u src/usr.sbin/zic/zic.8:1.5 src/usr.sbin/zic/zic.8:1.6
--- src/usr.sbin/zic/zic.8:1.5 Thu Mar 31 17:27:32 2022
+++ src/usr.sbin/zic/zic.8 Wed Sep 18 17:05:50 2024
@@ -1,5 +1,5 @@
-.\" $OpenBSD: zic.8,v 1.5 2022/03/31 17:27:32 naddy Exp $
-.Dd $Mdocdate: March 31 2022 $
+.\" $OpenBSD: zic.8,v 1.6 2024/09/18 17:05:50 millert Exp $
+.Dd $Mdocdate: September 18 2024 $
.Dt ZIC 8
.Os
.Sh NAME
@@ -240,6 +240,19 @@
is used to show where the
.Dq variable part
of the time zone abbreviation goes.
+Alternately, a format can use the pair of characters
+.Em %z
+to stand for the UTC offset in the form
+.No \(+- Ns Em hh ,
+.No \(+- Ns Em hhmm ,
+or
+.No \(+- Ns Em hhmmss ,
+using the shortest form that does not lose information, where
+.Em hh ,
+.Em mm ,
+and
+.Em ss
+are the hours, minutes, and seconds east (+) or west (\(mi) of UTC.
Alternately,
a slash
.Pq \&/
Index: src/usr.sbin/zic/zic.c
diff -u src/usr.sbin/zic/zic.c:1.26 src/usr.sbin/zic/zic.c:1.27
--- src/usr.sbin/zic/zic.c:1.26 Tue Oct 13 00:18:46 2020
+++ src/usr.sbin/zic/zic.c Wed Sep 18 17:05:50 2024
@@ -1,4 +1,4 @@
-/* $OpenBSD: zic.c,v 1.26 2020/10/13 00:18:46 deraadt Exp $ */
+/* $OpenBSD: zic.c,v 1.27 2024/09/18 17:05:50 millert Exp $ */
/*
** This file is in the public domain, so clarified as of
** 2006-07-17 by Arthur David Olson.
@@ -88,6 +88,7 @@
long z_gmtoff;
const char *z_rule;
const char *z_format;
+ char z_format_specifier;

long z_stdoff;

@@ -107,7 +108,7 @@
static void convert(long val, char *buf);
static void convert64(zic_t val, char *buf);
static void dolink(const char *fromfield, const char *tofield);
-static void doabbr(char *abbr, size_t size, const char *format,
+static void doabbr(char *abbr, size_t size, struct zone const *zp,
const char *letters, int isdst, int doquotes);
static void eat(const char *name, int num);
static void eats(const char *name, int num, const char *rname, int rnum);
@@ -148,6 +149,9 @@

extern char *__progname;

+/* Bound on length of what %z can expand to. */
+enum { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1 };
+
static int charcnt;
static int errors;
static const char *filename;
@@ -156,7 +160,7 @@
static int leapminyear;
static int leapmaxyear;
static int linenum;
-static int max_abbrvar_len;
+static int max_abbrvar_len = PERCENT_Z_LEN_BOUND;
static int max_format_len;
static zic_t max_time;
static int max_year;
@@ -739,7 +743,7 @@
** Note, though, that if there's no rule,
** a '%s' in the format is a bad thing.
*/
- if (strchr(zp->z_format, '%') != 0)
+ if (zp->z_format_specifier == 's')
error("%s in ruleless zone");
}
}
@@ -957,6 +961,7 @@
inzsub(char **fields, int nfields, int iscont)
{
char *cp;
+ char *cp1;
static struct zone z;
int i_gmtoff, i_rule, i_format;
int i_untilyear, i_untilmonth;
@@ -986,13 +991,22 @@
z.z_linenum = linenum;
z.z_gmtoff = gethms(fields[i_gmtoff], "invalid UTC offset", TRUE);
if ((cp = strchr(fields[i_format], '%')) != 0) {
- if (*++cp != 's' || strchr(cp, '%') != 0) {
+ if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
+ || strchr(fields[i_format], '/')) {
error("invalid abbreviation format");
return FALSE;
}
}
z.z_rule = ecpyalloc(fields[i_rule]);
- z.z_format = ecpyalloc(fields[i_format]);
+ z.z_format = cp1 = ecpyalloc(fields[i_format]);
+ z.z_format_specifier = cp ? *cp : '\0';
+ if (z.z_format_specifier == 'z') {
+ if (noise) {
+ warning("format '%%z' not handled by pre-2015 versions "
+ "of zic");
+ }
+ cp1[cp - fields[i_format]] = 's';
+ }
if (max_format_len < strlen(z.z_format))
max_format_len = strlen(z.z_format);
hasuntil = nfields > i_untilyear;
@@ -1635,19 +1649,58 @@
errx(1, "Error writing %s", fullname);
}

+static char const *
+abbroffset(char *buf, zic_t offset)
+{
+ char sign = '+';
+ int seconds, minutes;
+
+ if (offset < 0) {
+ offset = -offset;
+ sign = '-';
+ }
+
+ seconds = offset % SECSPERMIN;
+ offset /= SECSPERMIN;
+ minutes = offset % MINSPERHOUR;
+ offset /= MINSPERHOUR;
+ if (100 <= offset) {
+ error("%%z UTC offset magnitude exceeds 99:59:59");
+ return "%z";
+ } else {
+ char *p = buf;
+ *p++ = sign;
+ *p++ = '0' + offset / 10;
+ *p++ = '0' + offset % 10;
+ if (minutes | seconds) {
+ *p++ = '0' + minutes / 10;
+ *p++ = '0' + minutes % 10;
+ if (seconds) {
+ *p++ = '0' + seconds / 10;
+ *p++ = '0' + seconds % 10;
+ }
+ }
+ *p = '\0';
+ return buf;
+ }
+}
+
static void
-doabbr(char *abbr, size_t size, const char *format, const char *letters,
+doabbr(char *abbr, size_t size, struct zone const *zp, const char *letters,
int isdst, int doquotes)
{
char *cp, *slashp;
- int len;
+ size_t len;
+ char const *format = zp->z_format;

slashp = strchr(format, '/');
if (slashp == NULL) {
- if (letters == NULL)
- strlcpy(abbr, format, size);
- else
- snprintf(abbr, size, format, letters);
+ char letterbuf[PERCENT_Z_LEN_BOUND + 1];
+ if (zp->z_format_specifier == 'z')
+ letters = abbroffset(letterbuf, -zp->z_gmtoff);
+ else if (letters == NULL)
+ letters = "%s";
+ snprintf(abbr, size, format, letters);
} else if (isdst) {
strlcpy(abbr, slashp + 1, size);
} else {
@@ -1822,7 +1875,7 @@
if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0))
return;
abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
- doabbr(result, size, zp->z_format, abbrvar, FALSE, TRUE);
+ doabbr(result, size, zp, abbrvar, FALSE, TRUE);
ep = end(result, size);
if (stringoffset(ep, size - (ep - result), -zp->z_gmtoff) != 0) {
result[0] = '\0';
@@ -1831,7 +1884,7 @@
if (dstrp == NULL)
return;
ep = end(result, size);
- doabbr(ep, size - (ep - result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE);
+ doabbr(ep, size - (ep - result), zp, dstrp->r_abbrvar, TRUE, TRUE);
if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) {
ep = end(result, size);
if (stringoffset(ep, size - (ep - result),
@@ -1957,8 +2010,8 @@
startoff = zp->z_gmtoff;
if (zp->z_nrules == 0) {
stdoff = zp->z_stdoff;
- doabbr(startbuf, max_abbr_len + 1, zp->z_format,
- NULL, stdoff != 0, FALSE);
+ doabbr(startbuf, max_abbr_len + 1, zp, NULL,
+ stdoff != 0, FALSE);
type = addtype(oadd(zp->z_gmtoff, stdoff),
startbuf, stdoff != 0, startttisstd,
startttisgmt);
@@ -2041,7 +2094,7 @@
stdoff);
doabbr(startbuf,
max_abbr_len + 1,
- zp->z_format,
+ zp,
rp->r_abbrvar,
rp->r_stdoff != 0,
FALSE);
@@ -2052,7 +2105,7 @@
stdoff)) {
doabbr(startbuf,
max_abbr_len + 1,
- zp->z_format,
+ zp,
rp->r_abbrvar,
rp->r_stdoff != 0,
FALSE);
@@ -2060,7 +2113,7 @@
}
eats(zp->z_filename, zp->z_linenum,
rp->r_filename, rp->r_linenum);
- doabbr(ab, max_abbr_len + 1, zp->z_format,
+ doabbr(ab, max_abbr_len + 1, zp,
rp->r_abbrvar, rp->r_stdoff != 0, FALSE);
offset = oadd(zp->z_gmtoff, rp->r_stdoff);
type = addtype(offset, ab, rp->r_stdoff != 0,


--
Please keep replies on the mailing list.

No comments:

Post a Comment