ISO 8601 declares duration format as P[n]Y[n]M[n]DT[n]H[n]M[n]S
. For example, P3Y0.5MT6M
means "3 years, half of the month and 3 minutes".
There are various ways to convert it to unixtime/chrono::duration/whatever, but all solutions I found uses average month and year duration in seconds, which is not correct according to the standard. Instead, it should depend on the date, for example 01 Feb + P1M
should be 01 Mar
(+28 days), while 01 Mar + P1M
should be 01 Apr
(+31 days).
Which way could I implement this? Do I have any better choise than manual implementation with all these leap-years and other nasty things handling?
It would be best to use the date/time library that's being standardized for C++20. The cleverly named Date library can do the manipulations you suggest. It's year_month_day
type can do month and year addition the way you want it to work.
Also, the conversion to a time_point
is correct, to within the accuracy of the time_point
's integer type:
system_clock::time_point tp = sys_days{sun[5]/may/2016};
The year_month_day
type is implemented in terms of the Gregorian calendar, which is incorporated into ISO 8601. This conversion therefore does not care about "averages" or anything. It gets the system-clock's epoch, and counts the actual number of days from that epoch to the given date. It will factor in all of the idiosyncrasies of the Gregorian calendar. Including leap years. Including those years that ought to be leap years but aren't. These will be counted correctly.
tp
will therefore be the correct number of days, before the epoch or since, to the date in question.