LCOV - code coverage report
Current view: top level - src/datetime - datetime.c (source / functions) Coverage Total Hit
Test: colopresso Coverage Report Lines: 93.1 % 101 94
Test Date: 2025-12-13 15:41:21 Functions: 100.0 % 14 14
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-or-later
       3              :  *
       4              :  * This file is part of colopresso
       5              :  *
       6              :  * Copyright (C) 2025 COLOPL, Inc.
       7              :  *
       8              :  * Author: Go Kudo <g-kudo@colopl.co.jp>
       9              :  * Developed with AI (LLM) code assistance. See `NOTICE` for details.
      10              :  */
      11              : 
      12              : #include <stdbool.h>
      13              : #include <stdio.h>
      14              : #include <stdlib.h>
      15              : 
      16              : #include <time.h>
      17              : 
      18              : #include <colopresso/datetime.h>
      19              : #include <colopresso/portable.h>
      20              : 
      21              : struct _cpres_datetime_t {
      22              :   uint16_t year;
      23              :   uint8_t month;
      24              :   uint8_t day;
      25              :   uint8_t hour;
      26              :   uint8_t min;
      27              :   uint8_t sec;
      28              : };
      29              : 
      30            2 : cpres_datetime_timestamp_t cpres_datetime_timestamp(void) {
      31              :   time_t tm;
      32              : 
      33            2 :   tm = time(NULL);
      34            2 :   if (tm == -1) {
      35            0 :     return 0;
      36              :   }
      37              : 
      38            2 :   return (cpres_datetime_timestamp_t)tm;
      39              : }
      40              : 
      41           12 : void cpres_datetime_destroy(cpres_datetime_t *pdt) {
      42           12 :   if (!pdt) {
      43            1 :     return;
      44              :   }
      45              : 
      46           11 :   free(pdt);
      47              : }
      48              : 
      49           11 : cpres_datetime_t *cpres_datetime_create_from_timestamp(cpres_datetime_timestamp_t timestamp) {
      50              :   cpres_datetime_t *pdt;
      51              :   time_t t;
      52              :   struct tm tm;
      53              : 
      54           11 :   t = (time_t)timestamp;
      55           11 :   if (!gmtime_r(&t, &tm)) {
      56            0 :     return NULL;
      57              :   }
      58              : 
      59           11 :   pdt = (cpres_datetime_t *)malloc(sizeof(cpres_datetime_t));
      60           11 :   if (!pdt) {
      61            0 :     return NULL;
      62              :   }
      63              : 
      64           11 :   pdt->year = (uint16_t)(tm.tm_year + 1900);
      65           11 :   pdt->month = (uint8_t)tm.tm_mon + 1;
      66           11 :   pdt->day = (uint8_t)tm.tm_mday;
      67           11 :   pdt->hour = (uint8_t)tm.tm_hour;
      68           11 :   pdt->min = (uint8_t)tm.tm_min;
      69           11 :   pdt->sec = (uint8_t)tm.tm_sec;
      70              : 
      71           11 :   return pdt;
      72              : }
      73              : 
      74            1 : cpres_datetime_t *cpres_datetime_create(void) { return cpres_datetime_create_from_timestamp(cpres_datetime_timestamp()); }
      75              : 
      76            3 : cpres_datetime_timestamp_t cpres_datetime_get_timestamp(const cpres_datetime_t *pdt) {
      77            3 :   struct tm tm = {0};
      78              :   time_t local_time, gmt_time;
      79              :   struct tm gmt_tm;
      80              : 
      81            3 :   if (!pdt) {
      82            2 :     return 0;
      83              :   }
      84              : 
      85            1 :   tm.tm_year = pdt->year - 1900;
      86            1 :   tm.tm_mon = pdt->month - 1;
      87            1 :   tm.tm_mday = pdt->day;
      88            1 :   tm.tm_hour = pdt->hour;
      89            1 :   tm.tm_min = pdt->min;
      90            1 :   tm.tm_sec = pdt->sec;
      91            1 :   tm.tm_isdst = -1;
      92            1 :   colopresso_tm_set_gmt_offset(&tm);
      93              : 
      94            1 :   local_time = mktime(&tm);
      95            1 :   if (local_time == -1) {
      96            0 :     return 0;
      97              :   }
      98              : 
      99            1 :   gmtime_r(&local_time, &gmt_tm);
     100            1 :   gmt_time = mktime(&gmt_tm);
     101              : 
     102            1 :   return (cpres_datetime_timestamp_t)local_time + (local_time - gmt_time);
     103              : }
     104              : 
     105            5 : uint16_t cpres_datetime_get_year(const cpres_datetime_t *pdt) {
     106            5 :   if (!pdt) {
     107            2 :     return 0;
     108              :   }
     109              : 
     110            3 :   return pdt->year;
     111              : }
     112              : 
     113            4 : uint8_t cpres_datetime_get_mon(const cpres_datetime_t *pdt) {
     114            4 :   if (!pdt) {
     115            2 :     return 0;
     116              :   }
     117              : 
     118            2 :   return pdt->month;
     119              : }
     120              : 
     121            4 : uint8_t cpres_datetime_get_day(const cpres_datetime_t *pdt) {
     122            4 :   if (!pdt) {
     123            2 :     return 0;
     124              :   }
     125              : 
     126            2 :   return pdt->day;
     127              : }
     128              : 
     129            3 : uint8_t cpres_datetime_get_hour(const cpres_datetime_t *pdt) {
     130            3 :   if (!pdt) {
     131            2 :     return 0;
     132              :   }
     133              : 
     134            1 :   return pdt->hour;
     135              : }
     136              : 
     137            3 : uint8_t cpres_datetime_get_min(const cpres_datetime_t *pdt) {
     138            3 :   if (!pdt) {
     139            2 :     return 0;
     140              :   }
     141              : 
     142            1 :   return pdt->min;
     143              : }
     144              : 
     145            3 : uint8_t cpres_datetime_get_sec(const cpres_datetime_t *pdt) {
     146            3 :   if (!pdt) {
     147            2 :     return 0;
     148              :   }
     149              : 
     150            1 :   return pdt->sec;
     151              : }
     152              : 
     153              : /**
     154              :  * 32bit buildtime structure
     155              :  *
     156              :  * - UTC only.
     157              :  * - Theses are not supported:
     158              :  *   - summer time
     159              :  *   - time zone
     160              :  *
     161              :  *  year   (Y) : 12bit => 2^12-1 = 4095 use: ALL
     162              :  *  month  (M) : 4bit  => 2^4-1  = 15   use: 1-12
     163              :  *  day    (D) : 5bit  => 2^5-1  = 31   use: 1-31
     164              :  *  hour   (H) : 5bit  => 2^5-1  = 31   use: 0-23
     165              :  *  minute (M) : 6bit  => 2^6-1  = 63   use: 0-59
     166              :  *
     167              :  * HIGH                             LOW
     168              :  *  |--------------------------------|
     169              :  *  |YYYYYYYYYYYYMMMMDDDDDHHHHHMMMMMM|
     170              :  *  |--------------------------------|
     171              :  *  32           20  16   11   6     0
     172              :  *
     173              :  * e.g.
     174              :  * - Min: 0000-01-01 00:00 => 00000000000000010000100000000000 => 0x0010800
     175              :  * - Max: 4095-12-31 23:59 => 11111111111111001111110111111011 => 0xFFFCFDFB
     176              :  */
     177            4 : cpres_datetime_buildtime_t cpres_datetime_encode_buildtime(cpres_datetime_timestamp_t timestamp) {
     178              :   cpres_datetime_t *pdt;
     179              :   cpres_datetime_buildtime_t bt;
     180              : 
     181            4 :   pdt = cpres_datetime_create_from_timestamp(timestamp);
     182            4 :   if (!pdt) {
     183            0 :     return 0;
     184              :   }
     185              : 
     186            4 :   bt = 0;
     187            4 :   bt |= ((cpres_datetime_buildtime_t)(pdt->year) & 0xFFF) << 20;
     188            4 :   bt |= ((cpres_datetime_buildtime_t)(pdt->month) & 0xF) << 16;
     189            4 :   bt |= ((cpres_datetime_buildtime_t)(pdt->day) & 0x1F) << 11;
     190            4 :   bt |= ((cpres_datetime_buildtime_t)(pdt->hour) & 0x1F) << 6;
     191            4 :   bt |= ((cpres_datetime_buildtime_t)(pdt->min) & 0x3F);
     192              : 
     193            4 :   cpres_datetime_destroy(pdt);
     194              : 
     195            4 :   return bt;
     196              : }
     197              : 
     198            4 : cpres_datetime_timestamp_t cpres_datetime_decode_buildtime(cpres_datetime_buildtime_t buildtime) {
     199            4 :   struct tm t = {0};
     200              :   time_t local_time, gmt_time;
     201              :   struct tm gmt_tm;
     202              : 
     203            4 :   t.tm_year = ((buildtime >> 20) & 0xFFF) - 1900;
     204            4 :   t.tm_mon = ((buildtime >> 16) & 0xF) - 1;
     205            4 :   t.tm_mday = (buildtime >> 11) & 0x1F;
     206            4 :   t.tm_hour = (buildtime >> 6) & 0x1F;
     207            4 :   t.tm_min = buildtime & 0x3F;
     208            4 :   t.tm_sec = 0;
     209            4 :   t.tm_isdst = -1;
     210            4 :   colopresso_tm_set_gmt_offset(&t);
     211              : 
     212            4 :   local_time = mktime(&t);
     213            4 :   if (local_time == -1) {
     214            0 :     return 0;
     215              :   }
     216              : 
     217            4 :   gmtime_r(&local_time, &gmt_tm);
     218            4 :   gmt_time = mktime(&gmt_tm);
     219              : 
     220            4 :   return (cpres_datetime_timestamp_t)local_time + (local_time - gmt_time);
     221              : }
     222              : 
     223            2 : bool cpres_datetime_buildtime2str(cpres_datetime_buildtime_t buildtime, cpres_datetime_buildtime_str_t str) {
     224              :   cpres_datetime_t *pdt;
     225              : 
     226            2 :   pdt = cpres_datetime_create_from_timestamp(cpres_datetime_decode_buildtime(buildtime));
     227            2 :   if (pdt == NULL) {
     228            0 :     return false;
     229              :   }
     230              : 
     231            2 :   snprintf(str, CPRES_DT_BUILDTIME_LENGTH, "%04u-%02u-%02u %02u:%02u UTC", pdt->year, pdt->month, pdt->day, pdt->hour, pdt->min);
     232              : 
     233            2 :   cpres_datetime_destroy(pdt);
     234              : 
     235            2 :   return true;
     236              : }
        

Generated by: LCOV version 2.0-1