Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : * All rights reserved.
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : /**
21 : * @file
22 : * Various utility functions for dealing with time and dates.
23 : *
24 : */
25 :
26 : #include <limits>
27 : #include <stdint.h>
28 : #include <type_traits>
29 :
30 : #include <lib/core/CHIPCore.h>
31 : #include <lib/support/SafeInt.h>
32 :
33 : #include "TimeUtils.h"
34 :
35 : namespace chip {
36 :
37 : enum
38 : {
39 : // Number of days during the invariant part of the year (after the leap day).
40 : kDaysFromMarch1ToDecember31 = 306,
41 :
42 : // Number of years in a Gregorian "cycle", where a cycle is the 400-year period
43 : // over which the Gregorian calendar repeats.
44 : kYearsPerCycle = 400,
45 :
46 : // Total number of days within cycle.
47 : kDaysPerCycle = 146097,
48 :
49 : // Total number of days between 0000/03/01 and 1970/01/01.
50 : kEpochOffsetDays = 719468
51 : };
52 :
53 : /* Returns the number of days between January 1st and March 1st for a given year.
54 : */
55 6713097 : static inline uint8_t DaysToMarch1(uint16_t year)
56 : {
57 6713097 : if (IsLeapYear(year))
58 1630272 : return 60;
59 5082825 : return 59;
60 : }
61 :
62 : /* Converts a March-based month number (0=March, 1=April, etc.) to a March-1st based day of year (0=March 1st, 1=March 2nd, etc.).
63 : *
64 : * NOTE: This is based on the math described in http://howardhinnant.github.io/date_algorithms.html.
65 : */
66 28549251 : static uint16_t MarchBasedMonthToDayOfYear(uint8_t month)
67 : {
68 28549251 : return static_cast<uint16_t>((153 * month + 2) / 5);
69 : }
70 :
71 : /* Converts a March-1st based day of year (0=March 1st, 1=March 2nd, etc.) to a March-based month number (0=March, 1=April, etc.).
72 : */
73 14294079 : static uint8_t MarchBasedDayOfYearToMonth(uint16_t dayOfYear)
74 : {
75 : // This assumes dayOfYear is not using the full uint16_t range, so the cast
76 : // to uint8_t doesn't overflow.
77 14294079 : return static_cast<uint8_t>((5 * dayOfYear + 2) / 153);
78 : }
79 :
80 : /**
81 : * @def IsLeapYear
82 : *
83 : * @brief
84 : * Returns true if the given year is a leap year according to the Gregorian calendar.
85 : *
86 : * @param year
87 : * Gregorian calendar year.
88 : *
89 : */
90 7500335 : bool IsLeapYear(uint16_t year)
91 : {
92 7500335 : return (year % kLeapYearInterval) == 0 && ((year % kYearsPerCentury) != 0 || (year % kYearsPerCycle) == 0);
93 : }
94 :
95 : /**
96 : * @def DaysInMonth
97 : *
98 : * @brief
99 : * Returns the number of days in the given month/year.
100 : *
101 : * @param year
102 : * Gregorian calendar year.
103 : *
104 : * @param month
105 : * Month in standard form (1=January ... 12=December).
106 : *
107 : * @return
108 : * Number of days in the given month.
109 : */
110 10026729 : uint8_t DaysInMonth(uint16_t year, uint8_t month)
111 : {
112 : static const uint8_t daysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
113 :
114 10026729 : if (month == kFebruary && IsLeapYear(year))
115 193380 : return 29;
116 9833349 : if (month >= kJanuary && month <= kDecember)
117 9833349 : return daysInMonth[month - 1];
118 0 : return 0;
119 : }
120 :
121 : /**
122 : * @def FirstWeekdayOfYear
123 : *
124 : * @brief
125 : * Returns the day of the week for January 1st of the given year.
126 : *
127 : * @param year
128 : * Gregorian calendar year.
129 : *
130 : * @return
131 : * The day-of-week (0=Sunday...6=Saturday).
132 : */
133 0 : uint8_t FirstWeekdayOfYear(uint16_t year)
134 : {
135 : // Compute the day of the week for the first day of the given year using Gauss' algorithm.
136 : return static_cast<uint8_t>(
137 0 : (1 + 5 * ((year - 1) % kLeapYearInterval) + 4 * ((year - 1) % kYearsPerCentury) + 6 * ((year - 1) % kYearsPerCycle)) %
138 0 : kDaysPerWeek);
139 : }
140 :
141 : /**
142 : * @def OrdinalDateToCalendarDate
143 : *
144 : * @brief
145 : * Convert an ordinal date (year/day-of-year) to a calendar date.
146 : *
147 : * @param year
148 : * Gregorian calendar year.
149 : *
150 : * @param dayOfYear
151 : * Ordinal day of year, base 1 (1=January 1st, 2=January 2nd, etc.).
152 : *
153 : * @param month
154 : * [OUTPUT] Corresponding month in standard form (1=January ... 12=December).
155 : *
156 : * @param dayOfMonth
157 : * [OUTPUT] Corresponding day-of-month in standard form (1=1st, 2=2nd, etc.).
158 : *
159 : */
160 3652791 : void OrdinalDateToCalendarDate(uint16_t year, uint16_t dayOfYear, uint8_t & month, uint8_t & dayOfMonth)
161 : {
162 3652791 : uint8_t daysToMarch1 = DaysToMarch1(year);
163 :
164 : // Make dayOfYear base 0.
165 3652791 : dayOfYear = static_cast<uint16_t>(dayOfYear - 1);
166 :
167 : // Adjust dayOfYear to a March 1st base (i.e. 0 = March 1, 1 = March 2, etc.). This numbers January
168 : // and February at the end of the range, with the benefit that day numbering is identical between
169 : // standard and leap years with the exception of the leap day itself.
170 3652791 : if (dayOfYear < daysToMarch1)
171 592485 : dayOfYear = static_cast<uint16_t>(dayOfYear + kDaysFromMarch1ToDecember31);
172 : else
173 3060306 : dayOfYear = static_cast<uint16_t>(dayOfYear - daysToMarch1);
174 :
175 : // Compute a March-based month number (i.e. 0=March...11=February) from the day of year. This is based
176 : // on the logic in http://howardhinnant.github.io/date_algorithms.html.
177 3652791 : month = MarchBasedDayOfYearToMonth(dayOfYear);
178 :
179 : // Compute the days from March 1st to the start of the corresponding month.
180 3652791 : uint16_t daysFromMarch1ToStartOfMonth = MarchBasedMonthToDayOfYear(month);
181 :
182 : // Compute the day of month in standard form (1=1st, 2=2nd, etc.).
183 3652791 : dayOfMonth = static_cast<uint8_t>(dayOfYear - daysFromMarch1ToStartOfMonth + 1);
184 :
185 : // Convert the month number to standard form (1=January...12=December).
186 3652791 : month = static_cast<uint8_t>(month + (month < 10 ? 3 : -9));
187 3652791 : }
188 :
189 : /**
190 : * @def CalendarDateToOrdinalDate
191 : *
192 : * @brief
193 : * Convert an calendar date to ordinal form (year/day-of-year).
194 : *
195 : * @param year
196 : * Gregorian calendar year.
197 : *
198 : * @param month
199 : * Month in standard form (1=January ... 12=December).
200 : *
201 : * @param dayOfMonth
202 : * Day-of-month in standard form (1=1st, 2=2nd, etc.).
203 : *
204 : * @param dayOfYear
205 : * [OUTPUT] Ordinal day of year, base 1 (1=January 1st, 2=January 2nd, etc.).
206 : *
207 : */
208 3652791 : void CalendarDateToOrdinalDate(uint16_t year, uint8_t month, uint8_t dayOfMonth, uint16_t & dayOfYear)
209 : {
210 : // Convert month to a March-based month number (i.e. 0=March, 1=April, ...11=February).
211 3652791 : month = static_cast<uint8_t>(month + (month > kFebruary ? -3 : 9));
212 :
213 : // Compute the days from March 1st to the start of the corresponding month.
214 3652791 : dayOfYear = MarchBasedMonthToDayOfYear(month);
215 :
216 : // Adjust dayOfYear to be January-based (0=January 1st, 1=January 2nd...).
217 3652791 : if (dayOfYear < kDaysFromMarch1ToDecember31)
218 3060306 : dayOfYear = static_cast<uint16_t>(dayOfYear + DaysToMarch1(year));
219 : else
220 592485 : dayOfYear = static_cast<uint16_t>(dayOfYear - kDaysFromMarch1ToDecember31);
221 :
222 : // Add in day of month, converting to base 1 in the process.
223 3652791 : dayOfYear = static_cast<uint16_t>(dayOfYear + dayOfMonth);
224 3652791 : }
225 :
226 : /**
227 : * @def CalendarDateToDaysSinceUnixEpoch
228 : *
229 : * @brief
230 : * Convert a calendar date to the number of days since 1970-01-01.
231 : *
232 : * @param year
233 : * Gregorian calendar year in the range 1970 to 28276.
234 : *
235 : * @param month
236 : * Month in standard form (1=January ... 12=December).
237 : *
238 : * @param dayOfMonth
239 : * Day-of-month in standard form (1=1st, 2=2nd, etc.).
240 : *
241 : * @param daysSinceEpoch
242 : * [OUTPUT] Number of days since 1970-01-01.
243 : *
244 : * @return
245 : * True if the date was converted successfully. False if the given year falls outside the
246 : * representable range.
247 : *
248 : * @note
249 : * This function makes no attempt to verify the correct range of any arguments other than year.
250 : * Therefore callers must make sure the supplied values are valid prior to calling the function.
251 : */
252 10602381 : bool CalendarDateToDaysSinceUnixEpoch(uint16_t year, uint8_t month, uint8_t dayOfMonth, uint32_t & daysSinceEpoch)
253 : {
254 : // NOTE: This algorithm is based on the logic described in http://howardhinnant.github.io/date_algorithms.html.
255 :
256 : // Return immediately if the year is out of range.
257 10602381 : if (year < kUnixEpochYear || year > kMaxYearInDaysSinceUnixEpoch32)
258 : {
259 0 : daysSinceEpoch = UINT32_MAX;
260 0 : return false;
261 : }
262 :
263 : // Adjust the year and month to be March-based (i.e. 0=March, 1=April, ...11=February).
264 10602381 : if (month <= kFebruary)
265 : {
266 1719774 : year--;
267 1719774 : month = static_cast<uint8_t>(month + 9);
268 : }
269 : else
270 8882607 : month = static_cast<uint8_t>(month - 3);
271 :
272 : // Compute the days from March 1st to the start of the specified day.
273 10602381 : uint16_t dayOfYear = static_cast<uint16_t>(MarchBasedMonthToDayOfYear(month) + (dayOfMonth - 1));
274 :
275 : // Compute the 400-year Gregorian "cycle" within which the given year falls.
276 10602381 : uint16_t cycle = static_cast<uint16_t>(year / kYearsPerCycle);
277 :
278 : // Compute the relative year within the cycle.
279 10602381 : uint32_t yearOfCycle = year - (cycle * kYearsPerCycle);
280 :
281 : // Compute the relative day within the cycle, accounting for leap-years.
282 10602381 : uint32_t dayOfCycle =
283 10602381 : (yearOfCycle * kDaysPerStandardYear) + dayOfYear - (yearOfCycle / kYearsPerCentury) + (yearOfCycle / kLeapYearInterval);
284 :
285 : // Compute the total number of days since the start of the logical calendar (0000-03-01).
286 10602381 : uint32_t daysSinceCalendarStart = (cycle * kDaysPerCycle) + dayOfCycle;
287 :
288 : // Adjust the days value to be days since 1970-01-01.
289 10602381 : daysSinceEpoch = daysSinceCalendarStart - kEpochOffsetDays;
290 :
291 10602381 : return true;
292 : }
293 :
294 : /**
295 : * @def DaysSinceUnixEpochToCalendarDate
296 : *
297 : * @brief
298 : * Convert the number of days since 1970-01-01 to a calendar date.
299 : *
300 : * @param daysSinceEpoch
301 : * Number of days since 1970-01-01.
302 : *
303 : * @param year
304 : * [OUTPUT] Gregorian calendar year.
305 : *
306 : * @param month
307 : * [OUTPUT] Month in standard form (1=January ... 12=December).
308 : *
309 : * @param dayOfMonth
310 : * [OUTPUT] Day-of-month in standard form (1=1st, 2=2nd, etc.).
311 : *
312 : * @return
313 : * True if the conversion was successful. False if the year would not fit
314 : * in uint16_t.
315 : */
316 10641288 : bool DaysSinceUnixEpochToCalendarDate(uint32_t daysSinceEpoch, uint16_t & year, uint8_t & month, uint8_t & dayOfMonth)
317 : {
318 : // NOTE: This algorithm is based on the logic described in http://howardhinnant.github.io/date_algorithms.html.
319 10641288 : if (daysSinceEpoch / kDaysPerStandardYear + 1 > std::numeric_limits<std::remove_reference<decltype(year)>::type>::max())
320 : {
321 : // Our year calculation will likely overflow.
322 0 : return false;
323 : }
324 :
325 : // Adjust days value to be relative to 0000-03-01.
326 10641288 : daysSinceEpoch += kEpochOffsetDays;
327 :
328 : // Compute the 400-year Gregorian cycle in which the given day resides.
329 10641288 : uint32_t cycle = daysSinceEpoch / kDaysPerCycle;
330 :
331 : // Compute the relative day within the cycle.
332 10641288 : uint32_t dayOfCycle = daysSinceEpoch - (cycle * kDaysPerCycle);
333 :
334 : // Compute the relative year within the cycle, adjusting for leap-years.
335 10641288 : uint16_t yearOfCycle =
336 10641288 : static_cast<uint16_t>((dayOfCycle - dayOfCycle / 1460 + dayOfCycle / 36524 - dayOfCycle / 146096) / kDaysPerStandardYear);
337 :
338 : // Compute the relative day with the year.
339 10641288 : uint16_t dayOfYear = static_cast<uint16_t>(
340 10641288 : dayOfCycle - (yearOfCycle * kDaysPerStandardYear + yearOfCycle / kLeapYearInterval - yearOfCycle / kYearsPerCentury));
341 :
342 : // Compute a March-based month number (i.e. 0=March...11=February) from the day of year.
343 10641288 : month = MarchBasedDayOfYearToMonth(dayOfYear);
344 :
345 : // Compute the days from March 1st to the start of the corresponding month.
346 10641288 : uint16_t daysFromMarch1ToStartOfMonth = MarchBasedMonthToDayOfYear(month);
347 :
348 : // Compute the day of month in standard form (1=1st, 2=2nd, etc.).
349 10641288 : dayOfMonth = static_cast<uint8_t>(dayOfYear - daysFromMarch1ToStartOfMonth + 1);
350 :
351 : // Convert the month number to standard form (1=January...12=December).
352 10641288 : month = static_cast<uint8_t>(month + (month < 10 ? 3 : -9));
353 :
354 : // Compute the year, adjusting for the standard start of year (January).
355 10641288 : year = static_cast<uint16_t>(yearOfCycle + cycle * kYearsPerCycle);
356 10641288 : if (month <= kFebruary)
357 1724963 : year++;
358 10641288 : return true;
359 : }
360 :
361 : /**
362 : * @def AdjustCalendarDate
363 : *
364 : * @brief
365 : * Adjust a calendar date by a given number of days (positive or negative).
366 : *
367 : * @param year
368 : * [INPUT/OUTPUT] Gregorian calendar year.
369 : *
370 : * @param month
371 : * [INPUT/OUTPUT] Month in standard form (1=January ... 12=December).
372 : *
373 : * @param dayOfMonth
374 : * [INPUT/OUTPUT] Day-of-month in standard form (1=1st, 2=2nd, etc.).
375 : *
376 : * @param relativeDays
377 : * Number of days to add/subtract from given calendar date.
378 : *
379 : * @return
380 : * True if the adjustment succeeded. False if the adjustment would put us
381 : * outside the representable date range.
382 : *
383 : * @note
384 : * Given date must be equal to or greater than 1970-01-01.
385 : */
386 0 : bool AdjustCalendarDate(uint16_t & year, uint8_t & month, uint8_t & dayOfMonth, int32_t relativeDays)
387 : {
388 : uint32_t daysSinceEpoch;
389 0 : if (!CalendarDateToDaysSinceUnixEpoch(year, month, dayOfMonth, daysSinceEpoch))
390 : {
391 0 : return false;
392 : }
393 :
394 : // Make sure we can do our additions without overflowing.
395 0 : int64_t adjustedDays = static_cast<int64_t>(daysSinceEpoch) + relativeDays;
396 0 : if (!CanCastTo<uint32_t>(adjustedDays))
397 : {
398 0 : return false;
399 : }
400 :
401 0 : return DaysSinceUnixEpochToCalendarDate(static_cast<uint32_t>(adjustedDays), year, month, dayOfMonth);
402 : }
403 :
404 : /**
405 : * @def CalendarTimeToSecondsSinceUnixEpoch
406 : *
407 : * @brief
408 : * Convert a calendar date and time to the number of seconds since 1970-01-01 00:00:00 UTC.
409 : *
410 : * @details
411 : * This function is roughly equivalent to the POSIX gmtime() function with the exception
412 : * that the output time value is limited to positive values up to 2^32-1. This limits the
413 : * representable date range to the year 2105.
414 : *
415 : * @note
416 : * This function makes no attempt to verify the correct range of any arguments other than year.
417 : * Therefore callers must make sure the supplied values are valid prior to invocation.
418 : *
419 : * @param secondsSinceEpoch
420 : * Number of seconds since 1970-01-01 00:00:00 UTC. Note: this value is compatible with
421 : * *positive* values of the POSIX time_t value up to the year 2105.
422 : *
423 : * @param year
424 : * Gregorian calendar year in the range 1970 to 2105.
425 : *
426 : * @param month
427 : * Month in standard form (1=January ... 12=December).
428 : *
429 : * @param dayOfMonth
430 : * Day-of-month in standard form (1=1st, 2=2nd, etc.).
431 : *
432 : * @param hour
433 : * Hour (0-23).
434 : *
435 : * @param minute
436 : * Minute (0-59).
437 : *
438 : * @param second
439 : * Second (0-59).
440 : *
441 : * @return
442 : * True if the date/time was converted successfully. False if the given year falls outside the
443 : * representable range.
444 : */
445 496840 : bool CalendarTimeToSecondsSinceUnixEpoch(uint16_t year, uint8_t month, uint8_t dayOfMonth, uint8_t hour, uint8_t minute,
446 : uint8_t second, uint32_t & secondsSinceEpoch)
447 : {
448 : uint32_t daysSinceEpoch;
449 :
450 : // Return immediately if the year is out of range.
451 496840 : if (year < kUnixEpochYear || year > kMaxYearInSecondsSinceUnixEpoch32)
452 : {
453 0 : secondsSinceEpoch = UINT32_MAX;
454 0 : return false;
455 : }
456 :
457 496840 : CalendarDateToDaysSinceUnixEpoch(year, month, dayOfMonth, daysSinceEpoch);
458 :
459 496840 : secondsSinceEpoch = (daysSinceEpoch * kSecondsPerDay) + (hour * kSecondsPerHour) + (minute * kSecondsPerMinute) + second;
460 :
461 496840 : return true;
462 : }
463 : /**
464 : * @brief
465 : * Convert the number of seconds since 1970-01-01 00:00:00 UTC to a calendar date and time.
466 : *
467 : * @note
468 : * If secondsSinceEpoch is large enough this function will generate bad result. The way it is
469 : * used in this file the generated result should be valid. Specifically, the largest
470 : * possible value of secondsSinceEpoch input is (UINT32_MAX + kChipEpochSecondsSinceUnixEpoch),
471 : * when it is called from ChipEpochToCalendarTime().
472 : */
473 1032853 : static void SecondsSinceUnixEpochToCalendarTime(uint64_t secondsSinceEpoch, uint16_t & year, uint8_t & month, uint8_t & dayOfMonth,
474 : uint8_t & hour, uint8_t & minute, uint8_t & second)
475 : {
476 1032853 : uint32_t daysSinceEpoch = static_cast<uint32_t>(secondsSinceEpoch / kSecondsPerDay);
477 : static_assert((static_cast<uint64_t>(UINT32_MAX) + kChipEpochSecondsSinceUnixEpoch) / kSecondsPerDay <=
478 : std::numeric_limits<decltype(daysSinceEpoch)>::max(),
479 : "daysSinceEpoch would overflow");
480 1032853 : uint32_t timeOfDay = static_cast<uint32_t>(secondsSinceEpoch - (daysSinceEpoch * kSecondsPerDay));
481 :
482 : // Note: This call to DaysSinceUnixEpochToCalendarDate can't fail, because we
483 : // can't overflow a uint16_t year with a muximum possible value of the
484 : // secondsSinceEpoch input.
485 : static_assert((static_cast<uint64_t>(UINT32_MAX) + kChipEpochSecondsSinceUnixEpoch) / (kDaysPerStandardYear * kSecondsPerDay) +
486 : 1 <=
487 : std::numeric_limits<std::remove_reference<decltype(year)>::type>::max(),
488 : "What happened to our year or day lengths?");
489 1032853 : DaysSinceUnixEpochToCalendarDate(daysSinceEpoch, year, month, dayOfMonth);
490 :
491 1032853 : hour = static_cast<uint8_t>(timeOfDay / kSecondsPerHour);
492 1032853 : timeOfDay -= (hour * kSecondsPerHour);
493 1032853 : minute = static_cast<uint8_t>(timeOfDay / kSecondsPerMinute);
494 1032853 : timeOfDay -= (minute * kSecondsPerMinute);
495 1032853 : second = static_cast<uint8_t>(timeOfDay);
496 1032853 : }
497 :
498 : /**
499 : * @def SecondsSinceUnixEpochToCalendarTime
500 : *
501 : * @brief
502 : * Convert the number of seconds since 1970-01-01 00:00:00 UTC to a calendar date and time.
503 : *
504 : * @details
505 : * This function is roughly equivalent to the POSIX mktime() function, with the following
506 : * exceptions:
507 : *
508 : * - Input time values are limited to positive values up to 2^32-1. This limits the
509 : * representable date range to the year 2105.
510 : *
511 : * - The output time is always UTC (unlike mktime() which outputs time in the process's
512 : * configured timezone).
513 : *
514 : * @param secondsSinceEpoch
515 : * Number of seconds since 1970-01-01 00:00:00 UTC. Note: this value is compatible with
516 : * *positive* values of the POSIX time_t value up to the year 2105.
517 : *
518 : * @param year
519 : * [OUTPUT] Gregorian calendar year.
520 : *
521 : * @param month
522 : * [OUTPUT] Month in standard form (1=January ... 12=December).
523 : *
524 : * @param dayOfMonth
525 : * [OUTPUT] Day-of-month in standard form (1=1st, 2=2nd, etc.).
526 : *
527 : * @param hour
528 : * [OUTPUT] Hour (0-23).
529 : *
530 : * @param minute
531 : * [OUTPUT] Minute (0-59).
532 : *
533 : * @param second
534 : * [OUTPUT] Second (0-59).
535 : */
536 496730 : void SecondsSinceUnixEpochToCalendarTime(uint32_t secondsSinceEpoch, uint16_t & year, uint8_t & month, uint8_t & dayOfMonth,
537 : uint8_t & hour, uint8_t & minute, uint8_t & second)
538 : {
539 496730 : SecondsSinceUnixEpochToCalendarTime(static_cast<uint64_t>(secondsSinceEpoch), year, month, dayOfMonth, hour, minute, second);
540 496730 : }
541 :
542 497106 : bool CalendarToChipEpochTime(uint16_t year, uint8_t month, uint8_t dayOfMonth, uint8_t hour, uint8_t minute, uint8_t second,
543 : uint32_t & chipEpochTime)
544 : {
545 497106 : VerifyOrReturnError(year >= kChipEpochBaseYear && year <= kChipEpochMaxYear, false);
546 :
547 : uint32_t daysSinceUnixEpoch;
548 497106 : CalendarDateToDaysSinceUnixEpoch(year, month, dayOfMonth, daysSinceUnixEpoch);
549 :
550 497106 : chipEpochTime = ((daysSinceUnixEpoch - kChipEpochDaysSinceUnixEpoch) * kSecondsPerDay) + (hour * kSecondsPerHour) +
551 497106 : (minute * kSecondsPerMinute) + second;
552 :
553 497106 : return true;
554 : }
555 :
556 536123 : void ChipEpochToCalendarTime(uint32_t chipEpochTime, uint16_t & year, uint8_t & month, uint8_t & dayOfMonth, uint8_t & hour,
557 : uint8_t & minute, uint8_t & second)
558 : {
559 536123 : SecondsSinceUnixEpochToCalendarTime(static_cast<uint64_t>(chipEpochTime) + kChipEpochSecondsSinceUnixEpoch, year, month,
560 : dayOfMonth, hour, minute, second);
561 536123 : }
562 :
563 0 : bool ChipEpochToUnixEpochMicros(uint64_t chipEpochTimeMicros, uint64_t & outUnixEpochTimeMicros)
564 : {
565 0 : if ((chipEpochTimeMicros + kChipEpochUsSinceUnixEpoch) < kChipEpochUsSinceUnixEpoch)
566 : {
567 0 : return false;
568 : }
569 :
570 0 : outUnixEpochTimeMicros = chipEpochTimeMicros + kChipEpochUsSinceUnixEpoch;
571 0 : return true;
572 : }
573 :
574 0 : bool UnixEpochToChipEpochMicros(uint64_t unixEpochTimeMicros, uint64_t & outChipEpochTimeMicros)
575 : {
576 0 : VerifyOrReturnValue(unixEpochTimeMicros >= kChipEpochUsSinceUnixEpoch, false);
577 0 : outChipEpochTimeMicros = unixEpochTimeMicros - kChipEpochUsSinceUnixEpoch;
578 :
579 0 : return true;
580 : }
581 :
582 15 : bool UnixEpochToChipEpochTime(uint32_t unixEpochTimeSeconds, uint32_t & outChipEpochTimeSeconds)
583 : {
584 15 : VerifyOrReturnError(unixEpochTimeSeconds >= kChipEpochSecondsSinceUnixEpoch, false);
585 :
586 15 : outChipEpochTimeSeconds = unixEpochTimeSeconds - kChipEpochSecondsSinceUnixEpoch;
587 :
588 15 : return true;
589 : }
590 :
591 : } // namespace chip
|