* Date and time handling. @ 2020-04-08 3:56 ori 2020-04-08 6:48 ` [9front] " Steve Simon 2020-04-12 18:27 ` magma698hfsp273p9f 0 siblings, 2 replies; 9+ messages in thread From: ori @ 2020-04-08 3:56 UTC (permalink / raw) To: 9front Hi, Date handling on 9front 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. It allows working with times in multiple timezones at the same time. It is thread safe, including timezone loading. It allows parsing and formatting arbitrary formats. It lets you adjust the day and figure out the timeshift-shift adjusted time. Eventually, when it's ready (not yet), I'd like to put this into libc. The API additions are small, and all of our curent time APIs can be implemented trivially in terms of this api. At worst, I'd like to add the field additions from struct tmd to it. There are a few known bugs -- not all fields of the time struct are filled in yet, for example. The code is here: https://git.eigenstate.org/ori/date.git The formatted draft of the manpage is below, for comments and thoughts: TMDATE(2) TMDATE(2) NAME tmnow, tmtime, tmstime, tmshiftzone, tmparse, tmfmt, tmnorm, - convert date and time SYNOPSIS #include <u.h> #include <libc.h> typedef struct Tmd Tmd; struct { vlong abs; /* milliseconds 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 */ }; Tm *tmnow(Tm *tm, char *tz); Tm *tmtime(Tm *tm, vlong abs, char *tz); Tm *tmstime(Tm *tm, vlong sec, char *tz); Tm *tmshiftzone(Tm *dst, Tm *src, char *tz); Tm *tmparse(Tm *dst, char *fmt, char *tm); int tmfmt(char *buf, usize nbuf, char *fmt, Tm *tm); void tmnorm(Tm *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 represented as strings. They can be provided 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 name, any instant-dependent adjust- ments 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. 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. Tmshiftzone moves a time from one timezone to another, doing the appropriate conversions. Tmparse parses a time from a string according to the format argument. The format argument takes the form of a special date string, with the following components: 1,Jan,January Represents the month in numeric, short, or long form, respectively. 2 The day of month. 3,Mon,Monday The day of week in numeric, short, or long form, respectively. 3,15 The hour in 12 or 24 hour time, respectively. 4 The minute. 5 The second. 6,2006 The year in 2 and 4 digit forms, respectively. 7,MST The time zone offset in numeric or abbreviated form. As a special case, 7:00 will fill in both the hour and minutes in the timezone. _ Pads the following field with spaces. 0 Pads the fol- lowing field with zeroes. 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 nbuf-1 char- actters are written into buf, which is nul-terminated. Tmrecalc takes a manually adjusted Tm structure, and recal- culates the absolute time from it. This recalculation respects the time zone stored in struct tm. It also takes out of range values and wraps them around, simplifying cal- culations Tmfmtinstall installs a time format specifier %T. 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; print("local: %T0, tmnow(&t, "local")); print"gmt: %T0, tmnow(&t, "GMT")); print("eastern: %T0, tmnow(&t, "US_Pacific")); 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("same0); else print("different0); Add a day to two times. Because we picked daylight savings time to adjust over, only 23 hours are added. Tm t; tmparse(&t, nil, "Sun Nov 2 13:11:11 PST 2019"); tm.day++; tmrecalc(&t); print("%T", &t); /* Mon Nov 3 13:11:11 PST 2019 */ ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [9front] Date and time handling. 2020-04-08 3:56 Date and time handling ori @ 2020-04-08 6:48 ` Steve Simon 2020-04-09 14:12 ` ori 2020-04-12 6:20 ` ori 2020-04-12 18:27 ` magma698hfsp273p9f 1 sibling, 2 replies; 9+ messages in thread From: Steve Simon @ 2020-04-08 6:48 UTC (permalink / raw) To: 9front well done! i tried to do this years ago whilst writing an ical parser - and gave up in horror. -Steve > On 8 Apr 2020, at 5:57 am, ori@eigenstate.org wrote: > > Hi, > > Date handling on 9front 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. > > It allows working with times in multiple timezones at the > same time. It is thread safe, including timezone loading. > It allows parsing and formatting arbitrary formats. It lets > you adjust the day and figure out the timeshift-shift > adjusted time. > > Eventually, when it's ready (not yet), I'd like to put this > into libc. The API additions are small, and all of our curent > time APIs can be implemented trivially in terms of this api. > At worst, I'd like to add the field additions from struct tmd > to it. > > There are a few known bugs -- not all fields of the time struct > are filled in yet, for example. > > The code is here: > > https://git.eigenstate.org/ori/date.git > > The formatted draft of the manpage is below, for comments and > thoughts: > > TMDATE(2) TMDATE(2) > > NAME > tmnow, tmtime, tmstime, tmshiftzone, tmparse, tmfmt, tmnorm, > - convert date and time > > SYNOPSIS > #include <u.h> > #include <libc.h> > > typedef struct Tmd Tmd; > struct { > vlong abs; /* milliseconds 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 */ > }; > > Tm *tmnow(Tm *tm, char *tz); > Tm *tmtime(Tm *tm, vlong abs, char *tz); > Tm *tmstime(Tm *tm, vlong sec, char *tz); > Tm *tmshiftzone(Tm *dst, Tm *src, char *tz); > Tm *tmparse(Tm *dst, char *fmt, char *tm); > int tmfmt(char *buf, usize nbuf, char *fmt, Tm *tm); > void tmnorm(Tm *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 represented as strings. They can be provided > 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 name, any instant-dependent adjust- > ments 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. > > 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. > > Tmshiftzone moves a time from one timezone to another, doing > the appropriate conversions. > > Tmparse parses a time from a string according to the format > argument. The format argument takes the form of a special > date string, with the following components: > > 1,Jan,January > Represents the month in numeric, short, or long form, > respectively. > > 2 The day of month. > > 3,Mon,Monday > The day of week in numeric, short, or long form, > respectively. > > 3,15 The hour in 12 or 24 hour time, respectively. > > 4 The minute. > > 5 The second. > > 6,2006 > The year in 2 and 4 digit forms, respectively. > > 7,MST > The time zone offset in numeric or abbreviated form. > As a special case, 7:00 will fill in both the hour and > minutes in the timezone. > > _ Pads the following field with spaces. 0 Pads the fol- > lowing field with zeroes. > > 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 nbuf-1 char- > actters are written into buf, which is nul-terminated. > > Tmrecalc takes a manually adjusted Tm structure, and recal- > culates the absolute time from it. This recalculation > respects the time zone stored in struct tm. It also takes > out of range values and wraps them around, simplifying cal- > culations > > Tmfmtinstall installs a time format specifier %T. 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; > print("local: %T0, tmnow(&t, "local")); > print"gmt: %T0, tmnow(&t, "GMT")); > print("eastern: %T0, tmnow(&t, "US_Pacific")); > > 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("same0); > else > print("different0); > > Add a day to two times. Because we picked daylight savings > time to adjust over, only 23 hours are added. > > Tm t; > tmparse(&t, nil, "Sun Nov 2 13:11:11 PST 2019"); > tm.day++; > tmrecalc(&t); > print("%T", &t); /* Mon Nov 3 13:11:11 PST 2019 */ ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [9front] Date and time handling. 2020-04-08 6:48 ` [9front] " Steve Simon @ 2020-04-09 14:12 ` ori 2020-04-12 6:20 ` ori 1 sibling, 0 replies; 9+ messages in thread From: ori @ 2020-04-09 14:12 UTC (permalink / raw) To: steve, 9front > well done! > > i tried to do this years ago whilst writing an ical parser - and gave up in horror. > > -Steve > I should probably be absolutely clear: the manpage is aspirational, not documentational, though I think the hard parts are done or close. One thing that will annoy me: Currently, you need to specify the timezone as the filename, eg, "US_Eastern", rather than as the well known name, eg, "EST". There are two reasons for this. 1) We have no way to map from a timezone to the name, other than opening each timezone file and reading the first line. 2) The timezone name that we store in those files is wrong. We only have 3 characters for the timezone, so "Australia_Tasmania" becomes EST instead of AEST. I can hard-code a mapping, but that kind of sucks. I'd like to parse the IANA timezone database and generate files instead, either with a separate 'tzmap' file, or with duplicates for the abbreviated zones that we can open directly. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [9front] Date and time handling. 2020-04-08 6:48 ` [9front] " Steve Simon 2020-04-09 14:12 ` ori @ 2020-04-12 6:20 ` ori 1 sibling, 0 replies; 9+ messages in thread From: ori @ 2020-04-12 6:20 UTC (permalink / raw) To: steve, 9front > well done! > > i tried to do this years ago whilst writing an ical parser - and gave up in horror. > > -Steve > > >> >> The formatted draft of the manpage is below, for comments and >> thoughts: >> After some experimentation and discussion, the API was tweaked a bit. First, the formatting code was rewritten. Instead of using Go style format strings, I ended up going with moment.js[1] style format strings, with some tweaks and simplifications. There were too many edge cases in parsing the date and guessing at what the numbers meant for an elegant parser. Second, loading the timezone was made explicit. There were a number of errors that were easily ignored when loading invalid timezones, and timezone naming is a huge mess -- so making loading the timezone explicit. So, now you'd write: if((local = tmgetzone("local")) == nil) sysfatal("get zone: %r\n"); if(tmtime(&tm, 1586218416ll, local) == nil) sysfatal("now: %r"); tmfmt(buf, sizeof(buf), "YYYY/MM/DD hh:mm:ss", &tm); The updated manpage is below: TMDATE(2) TMDATE(2) NAME tmnow, tmtime, tmstime, tmshiftzone, tmparse, tmfmt, tmnorm, - convert date and time SYNOPSIS #include <u.h> #include <libc.h> typedef struct Tmd Tmd; struct { 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); Tm *tmnow(Tm *tm, char *tz); Tm *tmtime(Tm *tm, vlong abs, Tzone *tz); Tm *tmstime(Tm *tm, vlong sec, Tzone *tz); Tm *tmshiftzone(Tm *dst, Tm *src, Tzone *tz); Tm *tmparse(char *fmt, char *tm, Tzone *zone, Tm *dst); int tmfmt(char *buf, usize nbuf, char *fmt, Tm *tm); void tmnorm(Tm *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. Tmshiftzone moves a time from one timezone to another, doing the appropriate conversions. 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 %T. 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; print("local: %T0, tmnow(&t, "local")); print("gmt: %T0, tmnow(&t, "GMT")); print("eastern: %T0, tmnow(&t, "US_Pacific")); 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("same0); else print("different0); 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", &t); /* Mon Nov 3 13:11:11 PST 2019 */ ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Date and time handling. 2020-04-08 3:56 Date and time handling ori 2020-04-08 6:48 ` [9front] " Steve Simon @ 2020-04-12 18:27 ` magma698hfsp273p9f 2020-04-13 0:36 ` [9front] " ori 1 sibling, 1 reply; 9+ messages in thread From: magma698hfsp273p9f @ 2020-04-12 18:27 UTC (permalink / raw) To: 9front ori@eigenstate.org writes: > vlong abs; /* milliseconds since Jan 1 1970, GMT */ Do you really mean "GMT" or "UTC"? > 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) */ The "sec" field should probably be 0..60, to allow for leap seconds. Why do you specify the month as 0..11, rather than 1..12? > int tzoff; /* time zone delta from GMT */ Is the value in tzoff specified in seconds? Does a negative value mean east or west of GMT? > Time zones are represented as strings. They can be provided > as the abbreviated timezone name, the full timezone name, > the path to a timezone file, or an absolute offset in the > HHMM form. Is that HHMM allowed to have a leading +/- sign? > Tmtime converts the millisecond-resolution timestamp 'abs' > into a Tm struct in the requested timezone. If abs has millisecond resolution, and secs resolution of one second, then where in struct Tm do the fractional seconds go? > 6,2006 > The year in 2 and 4 digit forms, respectively. (2006 - 1900) != 6 > ISO-8601,RFC-3339 and RFC-2822 dates. It would also be nice to support ISO-8601 without the "T" separator between the date and time, which looks ugly and confuses people who haven't read the standard. I often use a space or "@" sign for improved readability, even though it's technically not ISO. > Tmfmt formats a Tm struct according to the format fmt. If > fmt is nil, we format as in ctime(2). At most nbuf-1 char- > actters are written into buf, which is nul-terminated. Does that (nbuf-1) count include the terminating NUL? > if(a.abs == b.abs) > print("same0); > else > print("different0); These are missing closing quotation marks. Also, how does the library handle dates prior to the Gregorian Reformation? It's nice to have input on a man page before it gets printed and bound. :) Thanks! ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [9front] Re: Date and time handling. 2020-04-12 18:27 ` magma698hfsp273p9f @ 2020-04-13 0:36 ` ori 2020-04-16 20:40 ` ori 0 siblings, 1 reply; 9+ messages in thread From: ori @ 2020-04-13 0:36 UTC (permalink / raw) To: magma698hfsp273p9f, 9front Thanks for the review. Good questions and comments! > ori@eigenstate.org writes: > >> vlong abs; /* milliseconds since Jan 1 1970, GMT */ > > Do you really mean "GMT" or "UTC"? I mean /adm/timezone/GMT. If we renamed it to UTC or TAI, I'd be happy with that too. Also, bug in comment: should be seconds. >> 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) */ > > The "sec" field should probably be 0..60, to allow for leap seconds. > Why do you specify the month as 0..11, rather than 1..12? Agreed. I'll change the comment for sec, though right now I dont' think our timezone files know how to represent leap seconds. Some fields are (IMO, unexpectedly) 0 based because this is intended to be merged with struct Tm eventaully. That means keeping the unfortunate definitions compatible. >> int tzoff; /* time zone delta from GMT */ > > Is the value in tzoff specified in seconds? Does a negative value mean > east or west of GMT? Seconds, west is negative, as in /adm/timezone/* >> Time zones are represented as strings. They can be provided >> as the abbreviated timezone name, the full timezone name, >> the path to a timezone file, or an absolute offset in the >> HHMM form. > > Is that HHMM allowed to have a leading +/- sign? Not yet implemented, but that'd make sense. >> Tmtime converts the millisecond-resolution timestamp 'abs' >> into a Tm struct in the requested timezone. > > If abs has millisecond resolution, and secs resolution of one second, > then where in struct Tm do the fractional seconds go? > abs :) But for now, I've changed resolution to seconds. I'd be willing to change it to anything else. >> 6,2006 >> The year in 2 and 4 digit forms, respectively. > > (2006 - 1900) != 6 Yep, but that's how Go specifies it. Anyways, I've completely changed the formatting. Now we have YY, YYYY for those two formats. >> ISO-8601,RFC-3339 and RFC-2822 dates. > > It would also be nice to support ISO-8601 without the "T" separator > between the date and time, which looks ugly and confuses people who > haven't read the standard. I often use a space or "@" sign for improved > readability, even though it's technically not ISO. Another change: I'm making the time parsing explicit. I think that the list of reasonable formats cam vary by caller, and if it turns out that it's duplicated a lot, we can revisit this decision easily. >> Tmfmt formats a Tm struct according to the format fmt. If >> fmt is nil, we format as in ctime(2). At most nbuf-1 char- >> actters are written into buf, which is nul-terminated. > > Does that (nbuf-1) count include the terminating NUL? No. I think I've rephrased this in the manpage already -- and, actually, just moved to format strings entirely. Now, you'd do something like: snprint(buf, sizeof(buf), "%τ", tmfmt(&tm, "YYYY MMM DD hh:mm:ss"); > >> if(a.abs == b.abs) >> print("same0); >> else >> print("different0); > > These are missing closing quotation marks. > > Also, how does the library handle dates prior to the Gregorian > Reformation? This library only deals with proleptic gregorian time. Which is jargon for "Get bent". > It's nice to have input on a man page before it gets printed and bound. > :) Thanks! It's nice to avoid making easy mistakes. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [9front] Re: Date and time handling. 2020-04-13 0:36 ` [9front] " ori @ 2020-04-16 20:40 ` ori 2020-05-04 4:08 ` ori 0 siblings, 1 reply; 9+ messages in thread From: ori @ 2020-04-16 20:40 UTC (permalink / raw) To: ori, magma698hfsp273p9f, 9front > Thanks for the review. Good questions and comments! > And thanks to joe9 for adding a bunch of test cases, which now all pass. I think the code is ready for testing. The next step, if there aren't any objections, will be to merge the `struct Tmd` with libc's `struct Tm`, and move this library over to use it. Once we've got some experience and are happy with this, I'd like to commit this to 9front and move utilities like date over to it. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [9front] Re: Date and time handling. 2020-04-16 20:40 ` ori @ 2020-05-04 4:08 ` ori 2020-05-05 17:29 ` magma698hfsp273p9f 0 siblings, 1 reply; 9+ messages in thread From: ori @ 2020-05-04 4:08 UTC (permalink / raw) To: ori, magma698hfsp273p9f, 9front >> Thanks for the review. Good questions and comments! >> > > And thanks to joe9 for adding a bunch of test cases, which > now all pass. I think the code is ready for testing. > > The next step, if there aren't any objections, will be to > merge the `struct Tmd` with libc's `struct Tm`, and move > this library over to use it. > > Once we've got some experience and are happy with this, I'd > like to commit this to 9front and move utilities like date > over to it. I started rewriting seconds(1), trying to loop together a mass of permutations of date formats, and decided I hate it. I think we should do two things with seconds: 1) Pick a common list of date formats we should try, one after the other. 2) add a '-f' option (same for date) that will accept a libdate format, instead of looping through them all and trying them one by one. What formats do people use with seconds? I'd like to propose the following, cribbed from Go's constant formats, but with the addition of RFC5322 asctime: WWW MMM DD hh:mm:ss YYYY RFC5322: Note: there are a lot of variants, and I'm considering adding a '?' modifier to indicate fuzzy parsing, where '1, 01, Jan, January' would all match '?M' WWW DD MMM YYYY hh:mm:ss Z WWW DD MMMM YYYY hh:mm:ss Z WWWW DD MMM YYYY hh:mm:ss Z WWWW DD MMMM YYYY hh:mm:ss Z WWW, DD-MM-YY hh:mm:ss Z WWW, DD-MM-YY hh:mm:ss Z WWW, DD-MMM-YY hh:mm:ss Z WWW, DD-MMMM-YY hh:mm:ss Z WWWW, DD-MM-YY hh:mm:ss Z WWWW, DD-MM-YY hh:mm:ss Z WWWW, DD-MMM-YY hh:mm:ss Z WWWW, DD-MMMM-YY hh:mm:ss Z RFC822/RFC8222: DD MMM YY hh:mm ZZZ DD MMM YY hh:mm Z RFC850: WW, DD-MMM-06 hh:mm:ss MST RFC1123: WWW, DD MMM YYYY hh:mm:ss ZZZ RFC1123Z: WWW, DD MMM YYYY hh:mm:ss ZZ RFC3339: YYYY-01-DDThh:mm:ss[Z]ZZ ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [9front] Re: Date and time handling. 2020-05-04 4:08 ` ori @ 2020-05-05 17:29 ` magma698hfsp273p9f 0 siblings, 0 replies; 9+ messages in thread From: magma698hfsp273p9f @ 2020-05-05 17:29 UTC (permalink / raw) To: 9front ori@eigenstate.org writes: > One thing that will annoy me: Currently, you need to specify the timezone > as the filename, eg, "US_Eastern", rather than as the well known name, > eg, "EST". There are two reasons for this. > > 1) We have no way to map from a timezone to the name, other than > opening each timezone file and reading the first line. > > 2) The timezone name that we store in those files is wrong. We only > have 3 characters for the timezone, so "Australia_Tasmania" becomes > EST instead of AEST. > > I can hard-code a mapping, but that kind of sucks. I'd like to parse > the IANA timezone database and generate files instead, either with a > separate 'tzmap' file, or with duplicates for the abbreviated zones > that we can open directly. # hm... why not use ndb? file=... to split the db among multiple files tzfs -f /ndb/timezone /srv/tzfs mount /srv/tzfs /adm/timezone > RFC3339: > YYYY-01-DDThh:mm:ss[Z]ZZ More human-readable variants of RFC3339: YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss Z YYYY-MM-DD hh:mm:ss z YYYY-MM-DD hh:mm:ss 0 YYYY-MM-DD hh:mm:ss +0400 YYYY-MM-DD hh:mm:ss -0400 YYYY-MM-DD hh:mm:ss +5 YYYY-MM-DD hh:mm:ss -0 YYYY-MM-DD @ hh:mm:ss YYYY-MM-DD @ hh:mm:ss +830 YYYY-MM-DD @ hh:mm:ss -0315 YYYY-MM-DD @ hh:mm:ss -3 YYYY-MM-DD @ hh:mm:ss +0 YYYY-MM-DD @ hh:mm:ss 0000 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-05-05 20:03 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-04-08 3:56 Date and time handling ori 2020-04-08 6:48 ` [9front] " Steve Simon 2020-04-09 14:12 ` ori 2020-04-12 6:20 ` ori 2020-04-12 18:27 ` magma698hfsp273p9f 2020-04-13 0:36 ` [9front] " ori 2020-04-16 20:40 ` ori 2020-05-04 4:08 ` ori 2020-05-05 17:29 ` magma698hfsp273p9f
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).