> Time zones are loaded by as name. Extra word?
On Sat, Apr 25, 2020, at 8:54 PM, [email protected] wrote: > Date handling on plan 9 is almost adequate today if you don't > have to parse dates or deal with timezones, and don't do > multithreading. Otherwise, it's difficult to get right, and > we often don't. > > We've got a crappy home-rolled date parser in seconds(1), > a few in the upas source tree to deal with mail formats, > and git9 has a few hacks around this as well. > > Out of tree, joe9 has been trying to write code that takes > stock information in one timezone and moves them to another, > and our APIs there are completely inadequate. > > So, I tried to write a library that is adequate, without > being complicated. > > The code lives here: > > https://git.eigenstate.org/ori/date.git > > I'll probably be merging in the changes between Tmd and Tm > soon, and committing to 9front, possibly even as part of libc. > > Some additional work is probably going to be needed to convert > from IANA zoneinfo to actually bring our timezone data up to > date. We may also need some timezone info format changes to > handle political (and leap second) changes. > > The manpage is attached below for review: > > TMDATE(2) TMDATE(2) > > NAME > tmnow, tmgetzone, tmtime, tmstime, tmparse, tmfmt, tmnorm, - > convert date and time > > SYNOPSIS > #include <u.h> > #include <libc.h> > > typedef struct Tmd Tmd; > struct Tmd { > vlong abs; /* seconds since Jan 1 1970, GMT */ > int sec; /* seconds (range 0..59) */ > int min; /* minutes (0..59) */ > int hour; /* hours (0..23) */ > int mday; /* day of the month (1..31) */ > int mon; /* month of the year (0..11) */ > int year; /* year A.D. - 1900 */ > int wday; /* day of week (0..6, Sunday = 0) */ > int yday; /* day of year (0..365) */ > char zone[]; /* time zone name */ > int tzoff; /* time zone delta from GMT */ > }; > > Tzone *tmgetzone(char *name); > Tmd *tmnow(Tmd *tm, char *tz); > Tmd *tmtime(Tmd *tm, vlong abs, Tzone *tz); > Tmd *tmstime(Tmd *tm, vlong sec, Tzone *tz); > Tmd *tmparse(char *fmt, char *tm, Tzone *zone, Tmd *dst); > int tmfmt(char *buf, usize nbuf, char *fmt, Tmd *tm); > void tmnorm(Tmd *tm); > void tmfmtinstall(char *fmt); > > DESCRIPTION > This family of functions handles simple date and time manpu- > lation. Times are represented as an absolute instant in > time, combined with a time zone. > > Time zones are loaded by as name. They can be specified as > the abbreviated timezone name, the full timezone name, the > path to a timezone file, or an absolute offset in the HHMM > form. > > When given as a timezone, any instant-dependent adjustments > such as leap seconds and daylight savings time will be > applied to the derived fields of struct tm, but will not > affect the absolute time. The time zone name local always > refers to the time in /env/timezone. The nil timezone > always refers to GMT. > > Tmgetzone loads a timezone by name. The returned timezone is > cached for the lifetime of the program, and should not be > freed. Loading a timezone repeatedly by name loads from the > cache, and does not leak. > > Tmnow gets the current time of day in the requested time > zone. > > Tmtime converts the millisecond-resolution timestamp 'abs' > into a Tm struct in the requested timezone. > > Tmstime is identical to tmtime, but accepts the time in sec- > onds. > > Tmparse parses a time from a string according to the format > argument. The result is returned in the timezone requested. > If there is a timezone in the date, then we tzshift to the > local timezone. > > The format argument takes contains zero or more of the fol- > lowing components: > > Y, YY, YYYY > Represents the year. YY prints the year in 2 digit > form. > > M, MM, MMM, MMMM > The month of the year, in unpadded numeric, padded > numeric, short name, or long name, respectively. > > D, DD > The day of month in unpadded or padded numeric form, > respectively. > > W, WW > The day of week in short or long name form, respec- > tively. > > h, hh > The hour in unpadded or padded form, respectively > > m, mm > The minute in unpadded or padded form, respectively > > s, ss > The second in unpadded or padded form, respectively > > z, Z, ZZ > The timezone in named, [+-]HHMM and [+-]HH:MM form, > respectively > > a, A Lower and uppercase 'am' and 'pm' specifiers, respec- > tively. > > [...] > Quoted text, copied directly to the output. > > Any characters not specified above are copied directly to > output, without modification. > > If the format argument is nil, it makes an attempt to parse > common human readable date formats. These formats include > ISO-8601,RFC-3339 and RFC-2822 dates. > > Tmfmt formats a Tm struct according to the format fmt. If > fmt is nil, we format as in ctime(2). At most characters are > written into buf, including the terminator. The format is > identical to tmparse. > > When parsing, any amount of whitespace is treated as a sin- > gle token. All string matches are case insensitive, and > zero padding is optional. > > Tmrecalc takes a manually adjusted Tm structure, and recal- > culates the absolute time from the year, mon, mday, hr, min > and sec fields. Other fields are ignored. This recalcula- > tion respects the time zone stored in struct tm. Out of > range values are wrapped. For example, December 32nd becomes > January 1st. > > Tmfmtinstall installs a time format specifier %τ. The time > format behaves as in tmfmt > > Examples > All examples assume tmfmtinstall has been called. > > Get the current date in the local timezone, GMT, and > US_Pacific time. Print it using the default format. > > Tm t; > Tzone *zl, *zp; > if((zl = tmgetzone("local") == nil) > sysfatal("load zone: %r"); > if((zp = tmgetzone("US_Pacific") == nil) > sysfatal("load zone: %r"); > print("local: %τ\n", tmnow(&t, zl)); > print("gmt: %τ\n", tmnow(&t, nil)); > print("eastern: %τ\n", tmnow(&t, zp)); > > Compare if two times are the same, regardless of timezone. > > Tm a, b; > > tmparse(&a, nil, "Tue Dec 10 12:36:00 PST 2019"); > tmparse(&b, nil, "Tue Dec 10 15:36:00 EST 2019"); > if(a.abs == b.abs) > print("same\n"); > else > print("different\n"); > > Convert from one timezone to another. > > Tm here, there; > Tzone *zl, *zp; > if((zl = tmgetzone("local") == nil) > sysfatal("load zone: %r"); > if((zp = tmgetzone("US_Pacific") == nil) > sysfatal("load zone: %r"); > if(tmnow(&here, zl) == nil) > sysfatal("get time: %r"); > if(tmtime(&there, here.abs, zp) == nil) > sysfatal("shift time: %r"); > > Add a day to two times. Because we picked daylight savings > time to adjust over, only 23 hours are added. > > Tm t; > tmparse(&t, "W MMM D hh:mm:ss z YYYY, "Sun Nov 2 13:11:11 PST 2019"); > tm.day++; > tmrecalc(&t); > print("%τ", &t); /* Mon Nov 3 13:11:11 PST 2019 */ > ------------------------------------------ 9fans: 9fans Permalink: https://9fans.topicbox.com/groups/9fans/T5b9f56a5fac852c2-M89899d7a4a8fbdc0ff8fb6a1 Delivery options: https://9fans.topicbox.com/groups/9fans/subscription
