differential code coverage report with master
Current view: top level - source/utils - date.cpp (source / functions) Coverage Total Hit UBC CBC
Current: coverage.info Lines: 97.2 % 72 70 2 70
Current Date: 2025-12-15 23:01:28 Functions: 100.0 % 10 10 10
Baseline: coverage_master.info Branches: 86.7 % 45 39 12 78
Baseline Date: 2025-12-15 23:01:27

             Branch data    TLA  Line data    Source code
       1                 :                : // Copyright (c) 2014-2022 Thomas Fussell
       2                 :                : // Copyright (c) 2024-2025 xlnt-community
       3                 :                : //
       4                 :                : // Permission is hereby granted, free of charge, to any person obtaining a copy
       5                 :                : // of this software and associated documentation files (the "Software"), to deal
       6                 :                : // in the Software without restriction, including without limitation the rights
       7                 :                : // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8                 :                : // copies of the Software, and to permit persons to whom the Software is
       9                 :                : // furnished to do so, subject to the following conditions:
      10                 :                : //
      11                 :                : // The above copyright notice and this permission notice shall be included in
      12                 :                : // all copies or substantial portions of the Software.
      13                 :                : //
      14                 :                : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15                 :                : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16                 :                : // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17                 :                : // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18                 :                : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19                 :                : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20                 :                : // THE SOFTWARE
      21                 :                : //
      22                 :                : // @license: http://www.opensource.org/licenses/mit-license.php
      23                 :                : // @author: see AUTHORS file
      24                 :                : 
      25                 :                : #include <ctime>
      26                 :                : 
      27                 :                : #include <xlnt/utils/date.hpp>
      28                 :                : #include <detail/time_helpers.hpp>
      29                 :                : 
      30                 :                : /// Invalid weekday for checking whether std::mktime was successful - see below.
      31                 :                : /// Must be outside of the range [0, 6].
      32                 :                : constexpr int INVALID_WDAY = -1;
      33                 :                : 
      34                 :                : namespace xlnt {
      35                 :                : 
      36                 :CBC          87 : date::date(int year_, int month_, int day_)
      37                 :             87 :     : year(year_), month(month_), day(day_), _is_null(false)
      38                 :                : {
      39                 :             87 : }
      40                 :                : 
      41                 :             50 : date date::from_number(int days_since_base_year, calendar base_date)
      42                 :                : {
      43                 :             50 :     date result(0, 0, 0);
      44                 :                : 
      45         [ +  + ]:             50 :     if (base_date == calendar::mac_1904)
      46                 :                :     {
      47                 :              1 :         days_since_base_year += 1462;
      48                 :                :     }
      49                 :                : 
      50         [ +  + ]:             50 :     if (days_since_base_year == 60)
      51                 :                :     {
      52                 :              1 :         result.day = 29;
      53                 :              1 :         result.month = 2;
      54                 :              1 :         result.year = 1900;
      55                 :                : 
      56                 :              1 :         return result;
      57                 :                :     }
      58         [ +  + ]:             49 :     else if (days_since_base_year < 60)
      59                 :                :     {
      60                 :             17 :         days_since_base_year++;
      61                 :                :     }
      62                 :                : 
      63                 :             49 :     int l = days_since_base_year + 68569 + 2415019;
      64                 :             49 :     int n = int((4 * l) / 146097);
      65                 :             49 :     l = l - int((146097 * n + 3) / 4);
      66                 :             49 :     int i = int((4000 * (l + 1)) / 1461001);
      67                 :             49 :     l = l - int((1461 * i) / 4) + 31;
      68                 :             49 :     int j = int((80 * l) / 2447);
      69                 :             49 :     result.day = l - int((2447 * j) / 80);
      70                 :             49 :     l = int(j / 11);
      71                 :             49 :     result.month = j + 2 - (12 * l);
      72                 :             49 :     result.year = 100 * (n - 49) + i + l;
      73                 :                : 
      74                 :             49 :     return result;
      75                 :                : }
      76                 :                : 
      77                 :              5 : bool date::operator==(const date &comparand) const
      78                 :                : {
      79   [ +  -  +  -  :              5 :     return year == comparand.year && month == comparand.month && day == comparand.day && _is_null == comparand._is_null;
             +  +  +  - ]
      80                 :                : }
      81                 :                : 
      82                 :              1 : bool date::operator!=(const date &comparand) const
      83                 :                : {
      84                 :              1 :     return !(*this == comparand);
      85                 :                : }
      86                 :                : 
      87                 :             27 : int date::to_number(calendar base_date) const
      88                 :                : {
      89         [ +  + ]:             27 :     if (_is_null)
      90                 :                :     {
      91            [ + ]:              1 :         throw xlnt::invalid_attribute("cannot convert invalid/empty date to a number");
      92                 :                :     }
      93                 :                : 
      94   [ +  +  +  +  :             26 :     if (day == 29 && month == 2 && year == 1900)
                   +  - ]
      95                 :                :     {
      96                 :              1 :         return 60;
      97                 :                :     }
      98                 :                : 
      99                 :             25 :     int days_since_1900 = int((1461 * (year + 4800 + int((month - 14) / 12))) / 4)
     100                 :             25 :         + int((367 * (month - 2 - 12 * ((month - 14) / 12))) / 12)
     101                 :             25 :         - int((3 * (int((year + 4900 + int((month - 14) / 12)) / 100))) / 4) + day - 2415019 - 32075;
     102                 :                : 
     103         [ +  + ]:             25 :     if (days_since_1900 <= 60)
     104                 :                :     {
     105                 :              1 :         days_since_1900--;
     106                 :                :     }
     107                 :                : 
     108         [ +  + ]:             25 :     if (base_date == calendar::mac_1904)
     109                 :                :     {
     110                 :              1 :         return days_since_1900 - 1462;
     111                 :                :     }
     112                 :                : 
     113                 :             24 :     return days_since_1900;
     114                 :                : }
     115                 :                : 
     116                 :              3 : date date::today()
     117                 :                : {
     118                 :              3 :     optional<std::tm> now = detail::localtime_safe(std::time(nullptr));
     119                 :                : 
     120         [ +  - ]:              3 :     if (now.is_set())
     121                 :                :     {
     122      [ +  +  + ]:              3 :         return date(1900 + now.get().tm_year, now.get().tm_mon + 1, now.get().tm_mday);
     123                 :                :     }
     124                 :                :     else
     125                 :                :     {
     126                 :UBC           0 :         return date();
     127                 :                :     }
     128                 :CBC           3 : }
     129                 :                : 
     130                 :              7 : int date::weekday() const
     131                 :                : {
     132         [ +  + ]:              7 :     if (!_is_null)
     133                 :                :     {
     134                 :              6 :         std::tm tm = std::tm();
     135                 :              6 :         tm.tm_wday = INVALID_WDAY;
     136                 :              6 :         tm.tm_mday = day;
     137                 :              6 :         tm.tm_mon = month - 1;
     138                 :              6 :         tm.tm_year = year - 1900;
     139                 :                : 
     140                 :                :         // Important: if the conversion made by std::mktime is successful, the time object is modified. All fields of time are updated
     141                 :                :         // to fit their proper ranges. time->tm_wday and time->tm_yday are recalculated using information available in other fields.
     142                 :                :         // IMPORTANT: the return value -1 could either be an error or mean 1 second before 1970-1-1. However, an application wishing to check
     143                 :                :         // for error situations should set tm_wday to a value less than 0 or greater than 6 before calling mktime(). On return, if tm_wday has not changed an error has occurred.
     144                 :              6 :         /*std::time_t time =*/std::mktime(&tm);
     145                 :                : 
     146         [ +  - ]:              6 :         if (tm.tm_wday != INVALID_WDAY)
     147                 :                :         {
     148                 :              6 :             return tm.tm_wday;
     149                 :                :         }
     150                 :                :         else
     151                 :                :         {
     152                 :UBC           0 :             return -1;
     153                 :                :         }
     154                 :                :     }
     155                 :                :     else
     156                 :                :     {
     157                 :CBC           1 :         return -1;
     158                 :                :     }
     159                 :                : }
     160                 :                : 
     161                 :             51 : int date::get_year() const
     162                 :                : {
     163         [ +  + ]:             51 :     if (_is_null)
     164                 :                :     {
     165            [ + ]:              1 :         throw xlnt::invalid_attribute("access to invalid/empty year of xlnt::date");
     166                 :                :     }
     167                 :                : 
     168                 :                : 
     169                 :             50 :     return year;
     170                 :                : }
     171                 :                : 
     172                 :             51 : int date::get_month() const
     173                 :                : {
     174         [ +  + ]:             51 :     if (_is_null)
     175                 :                :     {
     176            [ + ]:              1 :         throw xlnt::invalid_attribute("access to invalid/empty month of xlnt::date");
     177                 :                :     }
     178                 :                : 
     179                 :             50 :     return month;
     180                 :                : }
     181                 :                : 
     182                 :             51 : int date::get_day() const
     183                 :                : {
     184         [ +  + ]:             51 :     if (_is_null)
     185                 :                :     {
     186            [ + ]:              1 :         throw xlnt::invalid_attribute("access to invalid/empty day of xlnt::date");
     187                 :                :     }
     188                 :                : 
     189                 :             50 :     return day;
     190                 :                : }
     191                 :                : 
     192                 :                : } // namespace xlnt
        

Generated by: LCOV version 2.3.1-beta