Coverage Report

Created: 2023-12-08 07:04

/src/connectedhomeip/src/lib/support/TimeUtils.cpp
Line
Count
Source (jump to first uncovered line)
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
static inline uint8_t DaysToMarch1(uint16_t year)
59
0
{
60
0
    if (IsLeapYear(year))
61
0
        return 60;
62
0
    return 59;
63
0
}
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
static uint16_t MarchBasedMonthToDayOfYear(uint8_t month)
70
4.46k
{
71
4.46k
    return static_cast<uint16_t>((153 * month + 2) / 5);
72
4.46k
}
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
static uint8_t MarchBasedDayOfYearToMonth(uint16_t dayOfYear)
77
4.46k
{
78
    // This assumes dayOfYear is not using the full uint16_t range, so the cast
79
    // to uint8_t doesn't overflow.
80
4.46k
    return static_cast<uint8_t>((5 * dayOfYear + 2) / 153);
81
4.46k
}
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
bool IsLeapYear(uint16_t year)
94
0
{
95
0
    return (year % kLeapYearInterval) == 0 && ((year % kYearsPerCentury) != 0 || (year % kYearsPerCycle) == 0);
96
0
}
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
uint8_t DaysInMonth(uint16_t year, uint8_t month)
114
0
{
115
0
    static const uint8_t daysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
116
117
0
    if (month == kFebruary && IsLeapYear(year))
118
0
        return 29;
119
0
    if (month >= kJanuary && month <= kDecember)
120
0
        return daysInMonth[month - 1];
121
0
    return 0;
122
0
}
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
uint8_t FirstWeekdayOfYear(uint16_t year)
137
0
{
138
    // Compute the day of the week for the first day of the given year using Gauss' algorithm.
139
0
    return static_cast<uint8_t>(
140
0
        (1 + 5 * ((year - 1) % kLeapYearInterval) + 4 * ((year - 1) % kYearsPerCentury) + 6 * ((year - 1) % kYearsPerCycle)) %
141
0
        kDaysPerWeek);
142
0
}
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
void OrdinalDateToCalendarDate(uint16_t year, uint16_t dayOfYear, uint8_t & month, uint8_t & dayOfMonth)
164
0
{
165
0
    uint8_t daysToMarch1 = DaysToMarch1(year);
166
167
    // Make dayOfYear base 0.
168
0
    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
0
    if (dayOfYear < daysToMarch1)
174
0
        dayOfYear = static_cast<uint16_t>(dayOfYear + kDaysFromMarch1ToDecember31);
175
0
    else
176
0
        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
0
    month = MarchBasedDayOfYearToMonth(dayOfYear);
181
182
    // Compute the days from March 1st to the start of the corresponding month.
183
0
    uint16_t daysFromMarch1ToStartOfMonth = MarchBasedMonthToDayOfYear(month);
184
185
    // Compute the day of month in standard form (1=1st, 2=2nd, etc.).
186
0
    dayOfMonth = static_cast<uint8_t>(dayOfYear - daysFromMarch1ToStartOfMonth + 1);
187
188
    // Convert the month number to standard form (1=January...12=December).
189
0
    month = static_cast<uint8_t>(month + (month < 10 ? 3 : -9));
190
0
}
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
void CalendarDateToOrdinalDate(uint16_t year, uint8_t month, uint8_t dayOfMonth, uint16_t & dayOfYear)
212
0
{
213
    // Convert month to a March-based month number (i.e. 0=March, 1=April, ...11=February).
214
0
    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
0
    dayOfYear = MarchBasedMonthToDayOfYear(month);
218
219
    // Adjust dayOfYear to be January-based (0=January 1st, 1=January 2nd...).
220
0
    if (dayOfYear < kDaysFromMarch1ToDecember31)
221
0
        dayOfYear = static_cast<uint16_t>(dayOfYear + DaysToMarch1(year));
222
0
    else
223
0
        dayOfYear = static_cast<uint16_t>(dayOfYear - kDaysFromMarch1ToDecember31);
224
225
    // Add in day of month, converting to base 1 in the process.
226
0
    dayOfYear = static_cast<uint16_t>(dayOfYear + dayOfMonth);
227
0
}
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
bool CalendarDateToDaysSinceUnixEpoch(uint16_t year, uint8_t month, uint8_t dayOfMonth, uint32_t & daysSinceEpoch)
256
0
{
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
0
    if (year < kUnixEpochYear || year > kMaxYearInDaysSinceUnixEpoch32)
261
0
    {
262
0
        daysSinceEpoch = UINT32_MAX;
263
0
        return false;
264
0
    }
265
266
    // Adjust the year and month to be March-based (i.e. 0=March, 1=April, ...11=February).
267
0
    if (month <= kFebruary)
268
0
    {
269
0
        year--;
270
0
        month = static_cast<uint8_t>(month + 9);
271
0
    }
272
0
    else
273
0
        month = static_cast<uint8_t>(month - 3);
274
275
    // Compute the days from March 1st to the start of the specified day.
276
0
    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
0
    uint16_t cycle = static_cast<uint16_t>(year / kYearsPerCycle);
280
281
    // Compute the relative year within the cycle.
282
0
    uint32_t yearOfCycle = year - (cycle * kYearsPerCycle);
283
284
    // Compute the relative day within the cycle, accounting for leap-years.
285
0
    uint32_t dayOfCycle =
286
0
        (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
0
    uint32_t daysSinceCalendarStart = (cycle * kDaysPerCycle) + dayOfCycle;
290
291
    // Adjust the days value to be days since 1970-01-01.
292
0
    daysSinceEpoch = daysSinceCalendarStart - kEpochOffsetDays;
293
294
0
    return true;
295
0
}
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
bool DaysSinceUnixEpochToCalendarDate(uint32_t daysSinceEpoch, uint16_t & year, uint8_t & month, uint8_t & dayOfMonth)
320
4.46k
{
321
    // NOTE: This algorithm is based on the logic described in http://howardhinnant.github.io/date_algorithms.html.
322
4.46k
    if (daysSinceEpoch / kDaysPerStandardYear + 1 > std::numeric_limits<std::remove_reference<decltype(year)>::type>::max())
323
0
    {
324
        // Our year calculation will likely overflow.
325
0
        return false;
326
0
    }
327
328
    // Adjust days value to be relative to 0000-03-01.
329
4.46k
    daysSinceEpoch += kEpochOffsetDays;
330
331
    // Compute the 400-year Gregorian cycle in which the given day resides.
332
4.46k
    uint32_t cycle = daysSinceEpoch / kDaysPerCycle;
333
334
    // Compute the relative day within the cycle.
335
4.46k
    uint32_t dayOfCycle = daysSinceEpoch - (cycle * kDaysPerCycle);
336
337
    // Compute the relative year within the cycle, adjusting for leap-years.
338
4.46k
    uint16_t yearOfCycle =
339
4.46k
        static_cast<uint16_t>((dayOfCycle - dayOfCycle / 1460 + dayOfCycle / 36524 - dayOfCycle / 146096) / kDaysPerStandardYear);
340
341
    // Compute the relative day with the year.
342
4.46k
    uint16_t dayOfYear = static_cast<uint16_t>(
343
4.46k
        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
4.46k
    month = MarchBasedDayOfYearToMonth(dayOfYear);
347
348
    // Compute the days from March 1st to the start of the corresponding month.
349
4.46k
    uint16_t daysFromMarch1ToStartOfMonth = MarchBasedMonthToDayOfYear(month);
350
351
    // Compute the day of month in standard form (1=1st, 2=2nd, etc.).
352
4.46k
    dayOfMonth = static_cast<uint8_t>(dayOfYear - daysFromMarch1ToStartOfMonth + 1);
353
354
    // Convert the month number to standard form (1=January...12=December).
355
4.46k
    month = static_cast<uint8_t>(month + (month < 10 ? 3 : -9));
356
357
    // Compute the year, adjusting for the standard start of year (January).
358
4.46k
    year = static_cast<uint16_t>(yearOfCycle + cycle * kYearsPerCycle);
359
4.46k
    if (month <= kFebruary)
360
4.34k
        year++;
361
4.46k
    return true;
362
4.46k
}
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
bool AdjustCalendarDate(uint16_t & year, uint8_t & month, uint8_t & dayOfMonth, int32_t relativeDays)
390
0
{
391
0
    uint32_t daysSinceEpoch;
392
0
    if (!CalendarDateToDaysSinceUnixEpoch(year, month, dayOfMonth, daysSinceEpoch))
393
0
    {
394
0
        return false;
395
0
    }
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
0
    {
401
0
        return false;
402
0
    }
403
404
0
    return DaysSinceUnixEpochToCalendarDate(static_cast<uint32_t>(adjustedDays), year, month, dayOfMonth);
405
0
}
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
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
0
{
451
0
    uint32_t daysSinceEpoch;
452
453
    // Return immediately if the year is out of range.
454
0
    if (year < kUnixEpochYear || year > kMaxYearInSecondsSinceUnixEpoch32)
455
0
    {
456
0
        secondsSinceEpoch = UINT32_MAX;
457
0
        return false;
458
0
    }
459
460
0
    CalendarDateToDaysSinceUnixEpoch(year, month, dayOfMonth, daysSinceEpoch);
461
462
0
    secondsSinceEpoch = (daysSinceEpoch * kSecondsPerDay) + (hour * kSecondsPerHour) + (minute * kSecondsPerMinute) + second;
463
464
0
    return true;
465
0
}
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
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
4.46k
{
479
4.46k
    uint32_t daysSinceEpoch = static_cast<uint32_t>(secondsSinceEpoch / kSecondsPerDay);
480
4.46k
    static_assert((static_cast<uint64_t>(UINT32_MAX) + kChipEpochSecondsSinceUnixEpoch) / kSecondsPerDay <=
481
4.46k
                      std::numeric_limits<decltype(daysSinceEpoch)>::max(),
482
4.46k
                  "daysSinceEpoch would overflow");
483
4.46k
    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
4.46k
    static_assert((static_cast<uint64_t>(UINT32_MAX) + kChipEpochSecondsSinceUnixEpoch) / (kDaysPerStandardYear * kSecondsPerDay) +
489
4.46k
                          1 <=
490
4.46k
                      std::numeric_limits<std::remove_reference<decltype(year)>::type>::max(),
491
4.46k
                  "What happened to our year or day lengths?");
492
4.46k
    DaysSinceUnixEpochToCalendarDate(daysSinceEpoch, year, month, dayOfMonth);
493
494
4.46k
    hour = static_cast<uint8_t>(timeOfDay / kSecondsPerHour);
495
4.46k
    timeOfDay -= (hour * kSecondsPerHour);
496
4.46k
    minute = static_cast<uint8_t>(timeOfDay / kSecondsPerMinute);
497
4.46k
    timeOfDay -= (minute * kSecondsPerMinute);
498
4.46k
    second = static_cast<uint8_t>(timeOfDay);
499
4.46k
}
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
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
0
{
542
0
    SecondsSinceUnixEpochToCalendarTime(static_cast<uint64_t>(secondsSinceEpoch), year, month, dayOfMonth, hour, minute, second);
543
0
}
544
545
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
0
{
548
0
    VerifyOrReturnError(year >= kChipEpochBaseYear && year <= kChipEpochMaxYear, false);
549
550
0
    uint32_t daysSinceUnixEpoch;
551
0
    CalendarDateToDaysSinceUnixEpoch(year, month, dayOfMonth, daysSinceUnixEpoch);
552
553
0
    chipEpochTime = ((daysSinceUnixEpoch - kChipEpochDaysSinceUnixEpoch) * kSecondsPerDay) + (hour * kSecondsPerHour) +
554
0
        (minute * kSecondsPerMinute) + second;
555
556
0
    return true;
557
0
}
558
559
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
4.46k
{
562
4.46k
    SecondsSinceUnixEpochToCalendarTime(static_cast<uint64_t>(chipEpochTime) + kChipEpochSecondsSinceUnixEpoch, year, month,
563
4.46k
                                        dayOfMonth, hour, minute, second);
564
4.46k
}
565
566
bool UnixEpochToChipEpochTime(uint32_t unixEpochTime, uint32_t & chipEpochTime)
567
0
{
568
0
    VerifyOrReturnError(unixEpochTime >= kChipEpochSecondsSinceUnixEpoch, false);
569
570
0
    chipEpochTime = unixEpochTime - kChipEpochSecondsSinceUnixEpoch;
571
572
0
    return true;
573
0
}
574
575
} // namespace chip