9-Dates and Time Zones
9-Dates and Time Zones
Bjarne Stroustrup
Columbia University
www.stroustrup.com
• The readability of the code your client writes is far more important than
the readability of your library's synopsis or header.
microseconds
90 5
80
70 4
Kb
Hot cache
60
50 3
40 2
30
20 1
10
0 0
Bloomberg
I want to plan an event for the 5th Friday of every month which has one
Stroustrup - Date - Aarhus 2024 15
boost2
Big Picture
• C++20 <chrono>: A seamless extension of C++14 <chrono> into the realm of calendars.
• It is minimalistic.
• Date: the essential foundation
• Time zone: essential for many
• ISO week: iso_week.h (very useful for some)
• It won’t do everything you want.
• It provides efficient building blocks so you can easily do for yourself everything you want.
10-18 10-15 10-12 10-9 10-6 10-3 100 103 106 109 1012 1015 1018
year
month
Chrono (C++11, C++14) day
Predefined units: Date (C++20)
IANA tz database
“tz.h”
“date.h”
<chrono>
Now part of <chrono>
NTP Server
OS
conventional API
Date Algorithms
year_month_weekday_last
year_month_day_last
• sys_time is
• a serial-based time_point with a system determined resolution.
• Easily converted to sys_seconds and sys_days (and other) well-defined resolutions
• a simple count of clock ticks since the std::chrono::system_clock epoch (e.g., 1970y/1/1).
• the central theme of this library
• is nothing more than a alias for a time_point.
• Type safe
• auto t = system_clock::now(); // 2022-03-23 21:44:13.6544519 (clock’s precision)
auto today = floor<days>(t); // 2022-03-23 (precision: days)
Stroustrup - Date - Aarhus 2024 22
sys_time
• Time-line arithmetic is very efficient on sys_time
• Just ordinary integer arithmetic
• No day, month, year conversions until we want such
sys_time t0 = system_clock::now();
work();
auto t1 = system_clock::now(); // t0 is a sys_time; we use auto a lot in chrono
cout << duration_cast<milliseconds>(t1-t0).count() << "msec\n"; // specify unit
cout << t1-t0 << "\n";
• A sys_time is a time_point
• And so is a year_month_day
• Every date algorithm has been unit tested for every single day over
a range of +/- a million years.
• http://howardhinnant.github.io/date_algorithms.html
• “reasonably thorough” ☺
// C style
struct YMD_4 {
int16_t year;
uint8_t month;
// <chrono> uint8_t day;
};
date::year_month_day
make_year_month_day(int y, int m, int d) YMD_4
{ make_YMD_4(int y, int m, int d)
using namespace chrono; {
return year{y}/m/d; // “conventional API” return {(int16_t)y, (uint8_t)m, (uint8_t)d};
} }
Stroustrup - Date - Aarhus 2024 25
How expensive is this?
.globl __Z19make_year_month_dayiii .globl __Z10make_YMD_4iii
.align 4, 0x90 .align 4, 0x90
__Z19make_year_month_dayiii: __Z10make_YMD_4iii:
.cfi_startproc .cfi_startproc
## BB#0: ## BB#0:
pushq %rbp pushq %rbp
Ltmp2: Ltmp2:
.cfi_def_cfa_offset 16 .cfi_def_cfa_offset 16
Ltmp3: Ltmp3:
.cfi_offset %rbp, -16 .cfi_offset %rbp, -16
movq %rsp, %rbp movq %rsp, %rbp
Ltmp4: Ltmp4:
.cfi_def_cfa_register %rbp .cfi_def_cfa_register %rbp
shll $24, %edx shll $24, %edx
shll $16, %esi shll $16, %esi
andl $16711680, %esi andl $16711680, %esi
movzwl %di, %eax movzwl %di, %eax
orl %edx, %eax orl %esi, %eax
orl %esi, %eax orl %edx, %eax
popq %rbp popq %rbp
retq retq
.cfi_endproc .cfi_endproc
// C style
long shift_epoch(long t)
{
return t + 946684800;
}
// date.h
// did I get 946684800 right?
time_point shift_epoch(time_point t)
{
return t + (sys_time{January/1/2000} - sys_time{January/1/1970});
}
time_point shift_epoch(time_point t)
{
using namespace date;
return t + ( sys_time{January/1/2000} - sys_time{January/1/1970} );
}
convert to serial convert to serial
Convert to 946,684,800s
All at compile time!
Stroustrup - Date - Aarhus 2024 28
Type-safe objects
Not picking the right data structure is the most common
reason for performance problems.— Alexander Stepanov
• This library offers you a selection of data structures for dates and encourages
you to build more of your own.
• assert
assert(ymd.ok()); // Ensure the result is valid!
• throw
if (!ymd.ok())
throw std::domain_error{compose_message(ymd,m)};
• fix date
if (!ymd.ok())
ymd = ymd.year()/ymd.month()/last; // ymd == 2015_y/February/28
• fix month
if (!ymd.ok())
ymd = sys_time{ymd}; // ymd == 2015_y/March/3
Stroustrup - Date - Aarhus 2024 30
class year_month_day {
date::year y_; // exposition only
date::month m_; // exposition only
date::day d_; // exposition only
public:
constexpr year_month_day(const date::year& y, const date::month& m, const date::day& d) noexcept;
constexpr year_month_day(const year_month_day_last& ymdl) noexcept;
constexpr year_month_day(const sys_days& dp) noexcept;
constexpr year_month_day(const local_days& dp) noexcept;
// operators ==, !=, <, <=, >, >=, +, -, << for year and month
• I want to plan an event for the 5th Friday of every month which has one.
• This happens 4, sometimes 5 times a year.
• How easy is this to code?
• How expensive is it?
• Fair for API test? (probably)
2015-1-30
2015-5-29
2015-7-31
2015-10-30
<time in nanoseconds>
• I’m reporting the average of ten runs on an idle 4 core MacBook Pro, using this command line
microseconds
90 5
80
70 4
Kb
60
50 3
40 2
30
20 1
10
0 0
• <chrono>is small.
• <chrono> is fast.
• "The ability to create invalid dates
without being 'scolded' can be both a
readability and performance
advantage.“
-- Howard Hinnant
auto dp = floor<days>(system_clock::now());
auto ymd = year_month_day(dp);
cout << ymd << '\n'; // 2015-05-20
auto iso = iso_week(ymd);
cout << iso << '\n'; // 2015-W(21)-Wed
auto ymwd = year_month_weekday(iso);
cout << ymwd << '\n'; // 2015/May/Wed[3]
assert(year_month_day(iso) == ymd);
}
Stroustrup - Date - Aarhus 2024 54
Info
Warning: pre-C++20 versions, but still very good code
• https://howardhinnant.github.io/date/date.html
• Feedback for Howard appreciated
• Also:
• "iso_week.h" implements the ISO week calendar http://howardhinnant.github.io/date/iso_week.html
• "julian.h“ implements a proleptic Julian calendar http://howardhinnant.github.io/date/julian.html
• "islamic.h" implements a proleptic Islamic calendar http://howardhinnant.github.io/date/islamic.html