Re: [tz] Direct implementation of mktime_z
Hi Tony, On 2022-09-24, Tony Finch wrote:
You might also like https://dotat.at/@/2008-09-10-counting-the-days.html (That does things the hard way, rather than relying on tm_yday) and https://dotat.at/@/2008-09-15-the-date-of-the-count.html
Wow, that's some clever math you've done there; far nicer than the clumsy approach I'd used to canonicalize the year, month and day. It's a little slower than my clumsy approach in the case where the year, month and day are already in canonical form, but can be much faster when they're not. I'll incorporate those changes into my git project in the coming days, thank you! -Ted
On Sat, Sep 24, 2022 at 1:17 AM Ted Phelps via tz <tz@iana.org> wrote:
On 2022-09-24, Tony Finch wrote:
You might also like https://dotat.at/@/2008-09-10-counting-the-days.html (That does things the hard way, rather than relying on tm_yday) and https://dotat.at/@/2008-09-15-the-date-of-the-count.html
Wow, that's some clever math you've done there; far nicer than the clumsy approach I'd used to canonicalize the year, month and day. It's a little slower than my clumsy approach in the case where the year, month and day are already in canonical form, but can be much faster when they're not. I'll incorporate those changes into my git project in the coming days, thank you!
static inline int64_t daynum(int64_t year, int mon, int day) { // Rotate the start of the year to March so that the troublesome // leap day is last. Also, make March month number 4 to simplify // the calculation below. if (mon > 2) { mon += 1; } else { mon += 13; year -= 1; } // Compute the day number since the start of year 1. This clever // expression is thanks to Tony Finch; see his blog post for a // detailed explanation of what's going on here: // https://dotat.at/@/2008-09-10-counting-the-days.html return year * 1461 / 4 - year / 100 + year / 400 + mon * 153 / 5 + day - 428; } Assuming we want to model the proleptic Gregorian calendar, it would be nice if the output was linear over all inputs. At the moment, for example, daynum(0, 2, 29) and daynum(0, 3, 1) both return -305.
On 27/9/22 14:17, Bradley White wrote:
Assuming we want to model the proleptic Gregorian calendar, it would be nice if the output was linear over all inputs. At the moment, for example, daynum(0, 2, 29) and daynum(0, 3, 1) both return -305.
Ah, nice find! I forgot to compensate for division by negative numbers, and my test suite doesn't cover times before about 1800. I'll fix both shortcomings shortly. -Ted
On Sep 27, 2022, at 5:54 AM, Ted Phelps via tz <tz@iana.org> wrote:
On 27/9/22 14:17, Bradley White wrote:
Assuming we want to model the proleptic Gregorian calendar, it would be nice if the output was linear over all inputs. At the moment, for example, daynum(0, 2, 29) and daynum(0, 3, 1) both return -305.
Ah, nice find! I forgot to compensate for division by negative numbers, and my test suite doesn't cover times before about 1800. I'll fix both shortcomings shortly.
-Ted
If it helps, public domain calendrical algorithms for the proleptic Gregorian calendar that have a domain of validity of +/- millions of years, centered on the Unix epoch: http://howardhinnant.github.io/date_algorithms.html Howard
FWIW, the "indirect" implementation of mktime() (et.al.) wasn't for any efficiency aims - in fact, IMO, any application for which the efficiency of mktime() matters is probably doing something badly wrong, and the whole method ought to be reconsidered. Rather, I always considered it the right way for two reasons - it always works (regardless of what type time_t happens to be - back then that was even less settled than today ... dealing with unsigned time_t vs signed sometimes causes issues), and second, it means all the various rules (days/month, leap years, ....) need appear only in one place, rather than in two. The latter is what really swung it for me. kre
On 28/9/22 01:22, Robert Elz via tz wrote:
FWIW, the "indirect" implementation of mktime() (et.al.) wasn't for any efficiency aims - in fact, IMO, any application for which the efficiency of mktime() matters is probably doing something badly wrong, and the whole method ought to be reconsidered.
Perhaps. I noticed that one of the problems people have reported with adopting the "right" time zones is that many programs assume that a day is exactly 86,400 seconds and such. It's hard to argue that they shouldn't if it takes a significant amount of time to do it the right way. But that ship has probably already sailed.
Rather, I always considered it the right way for two reasons - it always works (regardless of what type time_t happens to be - back then that was even less settled than today ... dealing with unsigned time_t vs signed sometimes causes issues), and second, it means all the various rules (days/month, leap years, ....) need appear only in one place, rather than in two.
The latter is what really swung it for me.
That's certainly a reasonable choice to make, and the reason why I wanted to check with the list first instead of building something that no one wants. I'm not fussed either way. If there's interest, I'll put together a patch series to integrate the logic into localtime.c. If you folks would rather not have the additional code and associated maintenance costs then that's entirely fine with me. I'm happy to continue maintaining a separate, alternate library for people who want mktime to be faster for whatever reason. -Ted
On 28/9/22 00:45, Howard Hinnant wrote:
On Sep 27, 2022, at 5:54 AM, Ted Phelps via tz <tz@iana.org> wrote:
On 27/9/22 14:17, Bradley White wrote:
Assuming we want to model the proleptic Gregorian calendar, it would be nice if the output was linear over all inputs. At the moment, for example, daynum(0, 2, 29) and daynum(0, 3, 1) both return -305. Ah, nice find! I forgot to compensate for division by negative numbers, and my test suite doesn't cover times before about 1800. I'll fix both shortcomings shortly.
-Ted If it helps, public domain calendrical algorithms for the proleptic Gregorian calendar that have a domain of validity of +/- millions of years, centered on the Unix epoch:
Thanks, that's an excellent resource. I like the use of 'era' to refer to a block of 400 years. Is that a standard term? -Ted
On Sep 28, 2022, at 7:36 AM, Ted Phelps via tz <tz@iana.org> wrote:
On 28/9/22 00:45, Howard Hinnant wrote:
On Sep 27, 2022, at 5:54 AM, Ted Phelps via tz <tz@iana.org> wrote:
On 27/9/22 14:17, Bradley White wrote:
Assuming we want to model the proleptic Gregorian calendar, it would be nice if the output was linear over all inputs. At the moment, for example, daynum(0, 2, 29) and daynum(0, 3, 1) both return -305. Ah, nice find! I forgot to compensate for division by negative numbers, and my test suite doesn't cover times before about 1800. I'll fix both shortcomings shortly.
-Ted If it helps, public domain calendrical algorithms for the proleptic Gregorian calendar that have a domain of validity of +/- millions of years, centered on the Unix epoch:
Thanks, that's an excellent resource. I like the use of 'era' to refer to a block of 400 years. Is that a standard term?
I haven't seen the use of eras before, nor the use of the equation that transforms a day-of-era into a year-of-era before. However I would be surprised if this was the first use of these formulations. Howard
participants (4)
-
Bradley White -
Howard Hinnant -
Robert Elz -
Ted Phelps