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