1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3
4#ifndef BASE_TIME_H
5#define BASE_TIME_H
6
7#include <chrono>
8#include <cstdint>
9#include <ctime>
10
11/**
12 * Time utilities.
13 *
14 * @defgroup Time Time
15 *
16 * @ref Timestamp
17 */
18
19/**
20 * Timestamp related functions.
21 *
22 * @defgroup Timestamp Timestamps
23 *
24 * @ref Time
25 */
26
27/**
28 * Clears the cached sample of the high resolution timer.
29 *
30 * @ingroup Time
31 *
32 * @see time_get
33 */
34void set_new_tick();
35
36/**
37 * Fetches a sample from a high resolution timer and converts it to nanoseconds.
38 *
39 * @ingroup Time
40 *
41 * @return Current value of the timer in nanoseconds.
42 */
43std::chrono::nanoseconds time_get_nanoseconds();
44
45/**
46 * Fetches a sample from a high resolution timer.
47 *
48 * @ingroup Time
49 *
50 * @return Current value of the timer.
51 *
52 * @remark To know how fast the timer is ticking, see @link time_freq @endlink.
53 *
54 * @see time_freq
55 */
56int64_t time_get_impl();
57
58/**
59 * Fetches a cached sample from a high resolution timer.
60 *
61 * @ingroup Time
62 *
63 * @return Current value of the timer.
64 *
65 * @remark To know how fast the timer is ticking, see @link time_freq @endlink.
66 * @remark The value is cached for each tick, see @link set_new_tick @endlink.
67 * Uses @link time_get_impl @endlink to fetch the uncached sample.
68 *
69 * @see time_freq time_get_impl
70 */
71int64_t time_get();
72
73/**
74 * @ingroup Time
75 *
76 * @return The frequency of the high resolution timer.
77 */
78constexpr int64_t time_freq()
79{
80 using namespace std::chrono_literals;
81 return std::chrono::nanoseconds(1s).count();
82}
83
84/**
85 * Retrieves the current time as a UNIX timestamp.
86 *
87 * @ingroup Timestamp
88 *
89 * @return The time as a UNIX timestamp.
90 */
91int64_t time_timestamp();
92
93/**
94 * Retrieves the hours since midnight (0..23).
95 *
96 * @ingroup Time
97 *
98 * @return The current hour of the day.
99 */
100int time_houroftheday();
101
102/**
103 * A season of the year or seasonal event.
104 *
105 * @ingroup Time
106 */
107enum class ETimeSeason
108{
109 SPRING,
110 SUMMER,
111 AUTUMN,
112 WINTER,
113 EASTER,
114 HALLOWEEN,
115 XMAS,
116 NEWYEAR,
117};
118
119/**
120 * Retrieves the current season or event of the year.
121 *
122 * @ingroup Time
123 *
124 * @return The current season or event, see `ETimeSeason`.
125 */
126ETimeSeason time_season();
127
128/**
129 * Copies a timestamp of the current time in the format `year-month-day_hour-minute-second` to the string.
130 *
131 * @ingroup Timestamp
132 *
133 * @param buffer Pointer to a buffer that shall receive the timestamp string.
134 * @param buffer_size Size of the buffer.
135 *
136 * @remark Guarantees that buffer string will contain null-termination.
137 */
138void str_timestamp(char *buffer, int buffer_size);
139
140/**
141 * Copies a timestamp of the current time in the given format to the string.
142 *
143 * @ingroup Timestamp
144 *
145 * @param buffer Pointer to a buffer that shall receive the timestamp string.
146 * @param buffer_size Size of the buffer.
147 * @param format Time formatting string. See https://cppreference.com/w/c/chrono/strftime.html for format description.
148 * See `TimestampFormat` for common formats.
149 *
150 * @remark Guarantees that buffer string will contain null-termination.
151 */
152[[gnu::format(strftime, 3, 0)]] void str_timestamp_format(char *buffer, int buffer_size, const char *format);
153
154/**
155 * Copies a timestamp of the given time in the given format to the string.
156 *
157 * @ingroup Timestamp
158 *
159 * @param time The time value to represent as a string.
160 * @param buffer Pointer to a buffer that shall receive the timestamp string.
161 * @param buffer_size Size of the buffer.
162 * @param format Time formatting string. See https://cppreference.com/w/c/chrono/strftime.html for format description.
163 * See `TimestampFormat` for common formats.
164 *
165 * @remark Guarantees that buffer string will contain null-termination.
166 */
167[[gnu::format(strftime, 4, 0)]] void str_timestamp_ex(time_t time, char *buffer, int buffer_size, const char *format);
168
169/**
170 * Parses a string into a timestamp following a specified format.
171 *
172 * @ingroup Timestamp
173 *
174 * @param string Pointer to the string to parse.
175 * @param format The time format to use. See `TimestampFormat` for common formats.
176 * @param timestamp Pointer to the timestamp result.
177 *
178 * @return `true` on success, `false` if the string could not be parsed with the specified format.
179 */
180[[gnu::format(strftime, 2, 0)]] bool timestamp_from_str(const char *string, const char *format, time_t *timestamp);
181
182/**
183 * Timestamp format strings for the `str_timestamp_format`, `str_timestamp_ex` and `timestamp_from_str` functions.
184 *
185 * @ingroup Timestamp
186 *
187 * @see str_timestamp_format
188 * @see str_timestamp_ex
189 * @see timestamp_from_str
190 */
191namespace TimestampFormat
192{
193 inline const char *const TIME = "%H:%M:%S";
194 inline const char *const SPACE = "%Y-%m-%d %H:%M:%S";
195 inline const char *const NOSPACE = "%Y-%m-%d_%H-%M-%S";
196}
197
198/**
199 * Time formats for the `str_time` and `str_time_float` functions.
200 *
201 * @ingroup Timestamp
202 *
203 * @see str_time
204 * @see str_time_float
205 */
206enum class ETimeFormat
207{
208 DAYS,
209 HOURS,
210 MINS,
211 HOURS_CENTISECS,
212 MINS_CENTISECS,
213 SECS_CENTISECS,
214};
215
216/**
217 * Returns the number of milliseconds from a time float.
218 *
219 * Takes care to not introduce more rounding issues, which is what a naive
220 * `std::roundf(seconds * 1000.0)` would do.
221 *
222 * @ingroup Timestamp
223 *
224 * @param seconds Time in seconds.
225 *
226 * @return Number of milliseconds.
227 */
228int64_t time_milliseconds_from_seconds(float seconds);
229
230/**
231 * Formats a time string.
232 *
233 * @ingroup Timestamp
234 *
235 * @param centisecs Time in centiseconds.
236 * @param format Format of the time string, see `ETimeFormat`.
237 * @param buffer Pointer to a buffer that shall receive the timestamp string.
238 * @param buffer_size Size of the buffer.
239 *
240 * @return Number of bytes written.
241 */
242int str_time(int64_t centisecs, ETimeFormat format, char *buffer, int buffer_size);
243
244/**
245 * Formats a time string.
246 *
247 * @ingroup Timestamp
248 *
249 * @param secs Time in seconds.
250 * @param format Format of the time string, see `ETimeFormat`.
251 * @param buffer Pointer to a buffer that shall receive the timestamp string.
252 * @param buffer_size Size of the buffer.
253 *
254 * @remark The time is rounded to the nearest centisecond.
255 *
256 * @return Number of bytes written.
257 */
258int str_time_float(float secs, ETimeFormat format, char *buffer, int buffer_size);
259
260#endif
261