LCOV - code coverage report
Current view: top level - timelib - unixtime2tm.c (source / functions) Coverage Total Hit
Test: Coverage Report Lines: 65.0 % 120 78
Test Date: 2025-09-24 08:46:11 Functions: - 0 0

            Line data    Source code
       1              : /*
       2              :  * The MIT License (MIT)
       3              :  *
       4              :  * Copyright (c) 2015-2021 Derick Rethans
       5              :  * Copyright (c) 2021 MongoDB
       6              :  *
       7              :  * Permission is hereby granted, free of charge, to any person obtaining a copy
       8              :  * of this software and associated documentation files (the "Software"), to deal
       9              :  * in the Software without restriction, including without limitation the rights
      10              :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      11              :  * copies of the Software, and to permit persons to whom the Software is
      12              :  * furnished to do so, subject to the following conditions:
      13              :  *
      14              :  * The above copyright notice and this permission notice shall be included in
      15              :  * all copies or substantial portions of the Software.
      16              :  *
      17              :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      18              :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      19              :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      20              :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      21              :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      22              :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      23              :  * THE SOFTWARE.
      24              :  */
      25              : 
      26              : #include "timelib.h"
      27              : #include "timelib_private.h"
      28              : 
      29          692 : void timelib_unixtime2date(timelib_sll ts, timelib_sll *y, timelib_sll *m, timelib_sll *d)
      30              : {
      31              :         timelib_sll days, era, t;
      32              :         timelib_ull day_of_era, year_of_era, day_of_year, month_portion;
      33              : 
      34              :         /* Calculate days since algorithm's epoch (0000-03-01) */
      35          692 :         days = ts / SECS_PER_DAY + HINNANT_EPOCH_SHIFT;
      36              : 
      37              :         /* Adjustment for a negative time portion */
      38          692 :         t = ts % SECS_PER_DAY;
      39          692 :         days += (t < 0) ? -1 : 0;
      40              : 
      41              :         /* Calculate year, month, and day. Algorithm from:
      42              :          * http://howardhinnant.github.io/date_algorithms.html#civil_from_days */
      43          692 :         era = (days >= 0 ? days : days - DAYS_PER_ERA + 1) / DAYS_PER_ERA;
      44          692 :         day_of_era = days - era * DAYS_PER_ERA;
      45          692 :         year_of_era = (day_of_era - day_of_era / 1460 + day_of_era / 36524 - day_of_era / 146096) / DAYS_PER_YEAR;
      46          692 :         *y = year_of_era + era * YEARS_PER_ERA;
      47          692 :         day_of_year = day_of_era - (DAYS_PER_YEAR * year_of_era + year_of_era / 4 - year_of_era / 100);
      48          692 :         month_portion = (5 * day_of_year + 2) / 153;
      49          692 :         *d = day_of_year - (153 * month_portion + 2) / 5 + 1;
      50          692 :         *m = month_portion + (month_portion < 10 ? 3 : -9);
      51          692 :         *y += (*m <= 2);
      52              : 
      53              :         TIMELIB_DEBUG(printf("A: ts=%lld, year=%lld, month=%lld, day=%lld,", ts, *y, *m, *d););
      54          692 : }
      55              : 
      56              : /* Converts a Unix timestamp value into broken down time, in GMT */
      57          692 : void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)
      58              : {
      59              :         timelib_sll remainder;
      60              :         timelib_sll hours, minutes, seconds;
      61              : 
      62          692 :         timelib_unixtime2date(ts, &tm->y, &tm->m, &tm->d);
      63          692 :         remainder = ts % SECS_PER_DAY;
      64          692 :         remainder += (remainder < 0) * SECS_PER_DAY;
      65              : 
      66              :         /* That was the date, now we do the time */
      67          692 :         hours = remainder / 3600;
      68          692 :         minutes = (remainder - hours * 3600) / 60;
      69          692 :         seconds = remainder % 60;
      70              :         TIMELIB_DEBUG(printf(" hour=%lld, minute=%lld, second=%lld\n", hours, minutes, seconds););
      71              : 
      72          692 :         tm->h = hours;
      73          692 :         tm->i = minutes;
      74          692 :         tm->s = seconds;
      75          692 :         tm->z = 0;
      76          692 :         tm->dst = 0;
      77          692 :         tm->sse = ts;
      78          692 :         tm->sse_uptodate = 1;
      79          692 :         tm->tim_uptodate = 1;
      80          692 :         tm->is_localtime = 0;
      81          692 : }
      82              : 
      83          368 : void timelib_update_from_sse(timelib_time *tm)
      84              : {
      85              :         timelib_sll sse;
      86          368 :         int z = tm->z;
      87          368 :         signed int dst = tm->dst;
      88              : 
      89          368 :         sse = tm->sse;
      90              : 
      91          368 :         switch (tm->zone_type) {
      92            0 :                 case TIMELIB_ZONETYPE_ABBR:
      93              :                 case TIMELIB_ZONETYPE_OFFSET: {
      94            0 :                         timelib_unixtime2gmt(tm, tm->sse + tm->z + (tm->dst * 3600));
      95              : 
      96            0 :                         goto cleanup;
      97              :                 }
      98              : 
      99          128 :                 case TIMELIB_ZONETYPE_ID: {
     100          128 :                         int32_t  offset = 0;
     101              : 
     102          128 :                         timelib_get_time_zone_offset_info(tm->sse, tm->tz_info, &offset, NULL, NULL);
     103          128 :                         timelib_unixtime2gmt(tm, tm->sse + offset);
     104              : 
     105          128 :                         goto cleanup;
     106              :                 }
     107              : 
     108          240 :                 default:
     109          240 :                         timelib_unixtime2gmt(tm, tm->sse);
     110          240 :                         goto cleanup;
     111              :         }
     112          368 : cleanup:
     113          368 :         tm->sse = sse;
     114          368 :         tm->is_localtime = 1;
     115          368 :         tm->have_zone = 1;
     116          368 :         tm->z = z;
     117          368 :         tm->dst = dst;
     118          368 : }
     119              : 
     120           84 : void timelib_unixtime2local(timelib_time *tm, timelib_sll ts)
     121              : {
     122              :         timelib_time_offset *gmt_offset;
     123           84 :         timelib_tzinfo      *tz = tm->tz_info;
     124              : 
     125           84 :         switch (tm->zone_type) {
     126            0 :                 case TIMELIB_ZONETYPE_ABBR:
     127              :                 case TIMELIB_ZONETYPE_OFFSET: {
     128            0 :                         int z = tm->z;
     129            0 :                         signed int dst = tm->dst;
     130              : 
     131            0 :                         timelib_unixtime2gmt(tm, ts + tm->z + (tm->dst * 3600));
     132              : 
     133            0 :                         tm->sse = ts;
     134            0 :                         tm->z = z;
     135            0 :                         tm->dst = dst;
     136            0 :                         break;
     137              :                 }
     138              : 
     139           84 :                 case TIMELIB_ZONETYPE_ID:
     140           84 :                         gmt_offset = timelib_get_time_zone_info(ts, tz);
     141           84 :                         timelib_unixtime2gmt(tm, ts + gmt_offset->offset);
     142              : 
     143              :                         /* we need to reset the sse here as unixtime2gmt modifies it */
     144           84 :                         tm->sse = ts;
     145           84 :                         tm->dst = gmt_offset->is_dst;
     146           84 :                         tm->z = gmt_offset->offset;
     147           84 :                         tm->tz_info = tz;
     148              : 
     149           84 :                         timelib_time_tz_abbr_update(tm, gmt_offset->abbr);
     150           84 :                         timelib_time_offset_dtor(gmt_offset);
     151           84 :                         break;
     152              : 
     153            0 :                 default:
     154            0 :                         tm->is_localtime = 0;
     155            0 :                         tm->have_zone = 0;
     156            0 :                         return;
     157              :         }
     158              : 
     159           84 :         tm->is_localtime = 1;
     160           84 :         tm->have_zone = 1;
     161              : }
     162              : 
     163            0 : void timelib_set_timezone_from_offset(timelib_time *t, timelib_sll utc_offset)
     164              : {
     165            0 :         if (t->tz_abbr) {
     166            0 :                 timelib_free(t->tz_abbr);
     167              :         }
     168            0 :         t->tz_abbr = NULL;
     169              : 
     170            0 :         t->z = utc_offset;
     171            0 :         t->have_zone = 1;
     172            0 :         t->zone_type = TIMELIB_ZONETYPE_OFFSET;
     173            0 :         t->dst = 0;
     174            0 :         t->tz_info = NULL;
     175            0 : }
     176              : 
     177            0 : void timelib_set_timezone_from_abbr(timelib_time *t, timelib_abbr_info abbr_info)
     178              : {
     179            0 :         if (t->tz_abbr) {
     180            0 :                 timelib_free(t->tz_abbr);
     181              :         }
     182            0 :         t->tz_abbr = timelib_strdup(abbr_info.abbr);
     183              : 
     184            0 :         t->z = abbr_info.utc_offset;
     185            0 :         t->have_zone = 1;
     186            0 :         t->zone_type = TIMELIB_ZONETYPE_ABBR;
     187            0 :         t->dst = abbr_info.dst;
     188            0 :         t->tz_info = NULL;
     189            0 : }
     190              : 
     191          424 : void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz)
     192              : {
     193              :         timelib_time_offset *gmt_offset;
     194              : 
     195          424 :         gmt_offset = timelib_get_time_zone_info(t->sse, tz);
     196          424 :         t->z = gmt_offset->offset;
     197              : /*
     198              :         if (t->dst != gmt_offset->is_dst) {
     199              :                 printf("ERROR (%d, %d)\n", t->dst, gmt_offset->is_dst);
     200              :                 exit(1);
     201              :         }
     202              : */
     203          424 :         t->dst = gmt_offset->is_dst;
     204          424 :         t->tz_info = tz;
     205          424 :         if (t->tz_abbr) {
     206          340 :                 timelib_free(t->tz_abbr);
     207              :         }
     208          424 :         t->tz_abbr = timelib_strdup(gmt_offset->abbr);
     209          424 :         timelib_time_offset_dtor(gmt_offset);
     210              : 
     211          424 :         t->have_zone = 1;
     212          424 :         t->zone_type = TIMELIB_ZONETYPE_ID;
     213          424 : }
     214              : 
     215              : /* Converts the time stored in the struct to localtime if localtime = true,
     216              :  * otherwise it converts it to gmttime. This is only done when necessary
     217              :  * of course. */
     218            0 : int timelib_apply_localtime(timelib_time *t, unsigned int localtime)
     219              : {
     220            0 :         if (localtime) {
     221              :                 /* Converting from GMT time to local time */
     222              :                 TIMELIB_DEBUG(printf("Converting from GMT time to local time\n"););
     223              : 
     224              :                 /* Check if TZ is set */
     225            0 :                 if (!t->tz_info) {
     226              :                         TIMELIB_DEBUG(printf("E: No timezone configured, can't switch to local time\n"););
     227            0 :                         return -1;
     228              :                 }
     229              : 
     230            0 :                 timelib_unixtime2local(t, t->sse);
     231              :         } else {
     232              :                 /* Converting from local time to GMT time */
     233              :                 TIMELIB_DEBUG(printf("Converting from local time to GMT time\n"););
     234              : 
     235            0 :                 timelib_unixtime2gmt(t, t->sse);
     236              :         }
     237            0 :         return 0;
     238              : }
        

Generated by: LCOV version 2.0-1