summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/man/2/tmdate7
-rw-r--r--sys/src/libc/port/date.c28
2 files changed, 34 insertions, 1 deletions
diff --git a/sys/man/2/tmdate b/sys/man/2/tmdate
index 98c70eb8b..2b59649e6 100644
--- a/sys/man/2/tmdate
+++ b/sys/man/2/tmdate
@@ -114,6 +114,9 @@ and the unpadded and padded complete value, respectively.
.TP
.B Z, ZZ, ZZZ
The timezone in [+-]HHMM and [+-]HH:MM, and named form, respectively.
+If the named timezone matches the name of the local zone, then the
+local timezone will be used.
+Otherwise, we will attempt to use the named zones listed in RFC5322.
.TP
.B a, A
Lower and uppercase 'am' and 'pm' specifiers, respectively.
@@ -267,6 +270,10 @@ print("%τ", &t); /* Mon Nov 3 13:11:11 PST 2019 */
.SH BUGS
.PP
+Checking the timezone name against the local timezone is a
+dirty hack. The same date string may parse differently for
+people in different timezones.
+.PP
There is no way to format specifier for subsecond precision.
.PP
The timezone information that we ship is out of date.
diff --git a/sys/src/libc/port/date.c b/sys/src/libc/port/date.c
index 189bcb438..44ae15696 100644
--- a/sys/src/libc/port/date.c
+++ b/sys/src/libc/port/date.c
@@ -615,7 +615,7 @@ tmparse(Tm *tm, char *fmt, char *str, Tzone *tz, char **ep)
int depth, n, w, c0, zs, z0, z1, md, ampm, zoned, sloppy, tzo, ok;
vlong abs;
char *s, *p, *q;
- Tzone *zparsed;
+ Tzone *zparsed, *local;
Tzabbrev *a;
Tzoffpair *m;
@@ -774,6 +774,32 @@ tmparse(Tm *tm, char *fmt, char *str, Tzone *tz, char **ep)
switch(w){
case -1:
case 3:
+ /*
+ * Ugly Hack:
+ * Ctime is defined as printing a 3-character timezone
+ * name. The timezone name is ambiguous. For example,
+ * EST refers to both Australian and American eastern
+ * time. On top of that, we don't want to make the
+ * tzabbrev table exhaustive. So, we put in this hack:
+ *
+ * Before we consult the well known table of timezones,
+ * we check if the local time matches the timezone name.
+ *
+ * If you want unambiguous timezone parsing, use numeric
+ * timezone offsets (Z, ZZ formats).
+ */
+ if((local = tzload("local")) != nil){
+ if(cistrncmp(s, local->stname, strlen(local->stname)) == 0){
+ s += strlen(local->stname);
+ zparsed = local;
+ goto Zoneparsed;
+ }
+ if(cistrncmp(s, local->dlname, strlen(local->dlname)) == 0){
+ s += strlen(local->dlname);
+ zparsed = local;
+ goto Zoneparsed;
+ }
+ }
for(a = tzabbrev; a->abbr; a++){
n = strlen(a->abbr);
if(cistrncmp(s, a->abbr, n) == 0 && !isalpha(s[n]))