Matter SDK Coverage Report
Current view: top level - lib/support - TimeUtils.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 79.3 % 121 96
Test Date: 2025-01-17 19:00:11 Functions: 78.9 % 19 15

            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
        

Generated by: LCOV version 2.0-1