chrono
Everything is inside the namespace std::chrono
.
- Differences between:
std::time_t
std::tm
std::time()
std::time()
to get the number of elapsed seconds since the epoch time 1970.1.1 00:00:00
.
The returned type is time_t
. Note its precision is in seconds.
std::localtime
converts time_t
to a struct tm
in local time.
std::mktime()
converts a struct tm
into time_t
in local time.
std::asctime()
converts a struct tm
into a char*
in local time.
std::ctime()
converts a time_t
into a char*
in local time.
std::strftime
is more powerful.
std::this_thread::sleep_until
takes a timepoint as argument, while
std::this_thread::sleep_for
takes a duration as argument.
After using namespace std::chrono_literals;
or using std::chrono::operator""s
,
we can use auto s = 1s
.
./code/chrono/main.cc
1// Requires c++14
2// g++ -std=c++14 main.cc
3#include <assert.h>
4#include <chrono>
5#include <ctime>
6#include <iostream>
7#include <string>
8#include <thread>
9#include <type_traits>
10#include <vector>
11
12void test_duration() {
13 std::chrono::seconds s(1);
14 static_assert(
15 std::is_same<decltype(s),
16 std::chrono::duration<long long, std::ratio<1>>>::value,
17 "");
18 static_assert(sizeof(s) == sizeof(long long), "");
19
20 assert(s.count() == 1);
21
22 std::chrono::milliseconds ms(1);
23 static_assert(
24 std::is_same<decltype(ms), std::chrono::duration<
25 long long, std::ratio<1, 1000>>>::value,
26 "");
27
28 static_assert(sizeof(ms) == sizeof(long long), "");
29
30 assert(ms.count() == 1);
31 ms = s; // implicit cast
32 assert(ms.count() == 1000);
33
34 s = std::chrono::duration_cast<std::chrono::seconds>(ms);
35 assert(s.count() == 1);
36
37 using namespace std::chrono_literals;
38 auto s2 = 10s;
39 static_assert(std::is_same<decltype(s), decltype(s2)>::value, "");
40 assert(s2.count() == 10);
41
42 ms = s2;
43 assert(ms.count() == 1e4);
44 ms = ms + s;
45 assert(ms.count() == 11000);
46
47 // s = 3; // error
48 // std::cout << s << "\n"; // error
49
50 s = 1s;
51 ms = 1ms;
52 ms = s + ms;
53 assert(ms.count() == 1001);
54 s = std::chrono::duration_cast<std::chrono::seconds>(ms);
55 assert(s.count() == 1);
56
57 ms = 1100ms;
58 s = std::chrono::duration_cast<std::chrono::seconds>(ms); // truncated
59 assert(s.count() == 1);
60
61 std::chrono::minutes m = 1min;
62 s = m;
63 assert(s.count() == 60);
64
65 std::chrono::hours h = 1h;
66 s = h;
67 assert(s.count() == 60 * 60);
68
69 std::chrono::seconds s3; // s3.count() is uninitialized
70 // assert(s3.count() == 0); // does not hold
71}
72
73void test_time_1() {
74 // the resolution of std::time() is in seconds
75 std::time_t t = std::time(nullptr);
76 t = 1669039051;
77 // 16690369051
78 // 16690369052
79 // 16690369053
80 // t is an integer, representing the elapsed seconds since 1970.1.1 00:00 UTC
81
82 // the returned value points to a static allocated memory. Not thread safe.
83 // it is overwritten in the next call
84 std::tm *tm = std::localtime(&t);
85
86 // 2022-11-21 21:57:31
87 printf("%d-%d-%d %d:%d:%d\n", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
88 tm->tm_hour, tm->tm_min, tm->tm_sec);
89 // tm_year, years since 1900
90 // tm_mon: months since january (0-11)
91 std::vector<std::string> days = {"sunday", "saturday", "monday", "tuesday",
92 "wednesday", "thursday", "friday"};
93 // tm_wday: days since sunday (0-6)
94 printf("weekday: %s, %d\n", days[tm->tm_wday].c_str(), tm->tm_wday);
95 // weekday: saturday, 1
96
97 // tm_yday: days since january 1 (0-365)
98 printf("day of the year: %d\n", tm->tm_yday);
99 // day of the year: 324
100
101 // std::asctime() is not threadsafe
102 //
103 // Mon Nov 21 21:57:31 2022
104 printf("%s\n", std::asctime(tm));
105
106 // Mon Nov 21 13:57:31 2022
107 std::tm *gm = std::gmtime(&t); // UTC
108 printf("%s\n", std::asctime(gm));
109
110 // Mon Nov 21 21:57:31 2022
111 printf("%s\n", std::ctime(&t));
112 // std::ctime(&t) == std::asctime(std::localtime(&t))
113
114 // tm is in localtime
115 //
116 // https://en.cppreference.com/w/cpp/chrono/c/strftime
117 {
118 char s[100];
119 std::strftime(s, sizeof(s), "%Y", tm);
120 assert(s == std::string("2022"));
121 }
122
123 {
124 char s[100];
125 std::strftime(s, sizeof(s), "%y", tm);
126 assert(s == std::string("22")); // the last 2 digits of the year
127 }
128
129 {
130 char s[100];
131 std::strftime(s, sizeof(s), "%C", tm);
132 assert(s == std::string("20")); // the first 2 digits of the year
133 }
134
135 {
136 char s[100];
137 std::strftime(s, sizeof(s), "%b", tm);
138 assert(s == std::string("Nov"));
139 }
140
141 {
142 char s[100];
143 std::strftime(s, sizeof(s), "%B", tm);
144 assert(s == std::string("November"));
145 }
146
147 {
148 char s[100];
149 std::strftime(s, sizeof(s), "%m", tm);
150 assert(s == std::string("11")); // month
151 }
152
153 {
154 char s[100];
155 std::strftime(s, sizeof(s), "%U", tm);
156 // week of the year. Sunday is the first day of the week
157 assert(s == std::string("47"));
158 }
159
160 {
161 char s[100];
162 std::strftime(s, sizeof(s), "%W", tm);
163 // week of the year. Monday is the first day of the week
164 assert(s == std::string("47"));
165 }
166
167 {
168 char s[100];
169 std::strftime(s, sizeof(s), "%j", tm);
170 // day of the year: 1-366
171 assert(s == std::string("325"));
172 }
173
174 {
175 char s[100];
176 std::strftime(s, sizeof(s), "%d", tm);
177 // day of the month: 1-31
178 assert(s == std::string("21"));
179 }
180}
181
182void test_time_2() {
183 struct std::tm tm {};
184 tm.tm_year = 1970 - 1900;
185 tm.tm_mon = 0;
186 tm.tm_mday = 1;
187 tm.tm_sec = 1;
188 tm.tm_isdst = 0;
189 // Cannot use std::mktime() here since it treats tm as localtime
190 // std::time_t t = std::mktime(&tm);
191
192 std::time_t t = timegm(&tm);
193 assert(t == 1); // epoch time is 1970, january 1, 00:00:00
194}
195
196void test_timepoint() {
197 {
198 // conversion between timepoint and time_t
199 std::time_t t = std::time(nullptr);
200
201 std::chrono::system_clock::time_point tp =
202 std::chrono::system_clock::from_time_t(t);
203
204 auto duration = tp.time_since_epoch();
205 auto s = std::chrono::duration_cast<std::chrono::seconds>(duration);
206 assert(t == s.count());
207 }
208
209 {
210 std::chrono::system_clock::time_point now =
211 std::chrono::system_clock::now();
212 std::time_t t = std::chrono::system_clock::to_time_t(now);
213 std::time_t t2 = std::time(nullptr);
214 assert(t == t2);
215 }
216}
217
218void test_sleep() {
219 std::time_t t = std::time(nullptr);
220 // note: std::ctime contains "\n"
221 std::cout << "start to sleep at " << std::ctime(&t);
222 auto now = std::chrono::steady_clock::now();
223 using std::chrono::operator""s;
224 std::this_thread::sleep_until(now + 1s);
225 t = std::time(nullptr);
226 std::cout << "finish sleeping at " << std::ctime(&t);
227}
228
229void test_sleep_2() {
230 auto start = std::chrono::steady_clock::now();
231 using std::chrono::operator""ms;
232 // use sleep_until with a timepoint
233 std::this_thread::sleep_until(start + 500ms);
234 auto end = std::chrono::steady_clock::now();
235 std::cout << "finish sleeping at "
236 << std::chrono::duration<double, std::milli>(end - start).count()
237 << " ms\n";
238}
239
240void test_sleep_3() {
241 auto start = std::chrono::steady_clock::now();
242 using std::chrono::operator""ms;
243 // use sleep_for with a duration
244 std::this_thread::sleep_for(10ms);
245 auto end = std::chrono::steady_clock::now();
246 std::cout << "finish sleeping at "
247 << std::chrono::duration<double, std::milli>(end - start).count()
248 << " ms\n";
249}
250
251int main() {
252 test_duration();
253 test_time_1();
254 test_time_2();
255 test_timepoint();
256 test_sleep();
257 test_sleep_2();
258 test_sleep_3();
259 return 0;
260}