root/ext/date/lib/unixtime2tm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. timelib_unixtime2gmt
  2. timelib_update_from_sse
  3. timelib_unixtime2local
  4. timelib_set_timezone_from_offset
  5. timelib_set_timezone_from_abbr
  6. timelib_set_timezone
  7. timelib_apply_localtime

   1 /*
   2  * The MIT License (MIT)
   3  *
   4  * Copyright (c) 2015 Derick Rethans
   5  *
   6  * Permission is hereby granted, free of charge, to any person obtaining a copy
   7  * of this software and associated documentation files (the "Software"), to deal
   8  * in the Software without restriction, including without limitation the rights
   9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10  * copies of the Software, and to permit persons to whom the Software is
  11  * furnished to do so, subject to the following conditions:
  12  *
  13  * The above copyright notice and this permission notice shall be included in
  14  * all copies or substantial portions of the Software.
  15  *
  16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22  * THE SOFTWARE.
  23  */
  24 
  25 #include "timelib.h"
  26 
  27 #include <stdio.h>
  28 
  29 #ifdef HAVE_STDLIB_H
  30 #include <stdlib.h>
  31 #endif
  32 
  33 #ifdef HAVE_STRING_H
  34 #include <string.h>
  35 #else
  36 #include <strings.h>
  37 #endif
  38 
  39 static int month_tab_leap[12] = { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  40 static int month_tab[12] =      { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  41 
  42 
  43 /* Converts a Unix timestamp value into broken down time, in GMT */
  44 void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)
  45 {
  46         timelib_sll days, remainder, tmp_days;
  47         timelib_sll cur_year = 1970;
  48         timelib_sll i;
  49         timelib_sll hours, minutes, seconds;
  50         int *months;
  51 
  52         days = ts / SECS_PER_DAY;
  53         remainder = ts - (days * SECS_PER_DAY);
  54         if (ts < 0 && remainder == 0) {
  55                 days++;
  56                 remainder -= SECS_PER_DAY;
  57         }
  58         TIMELIB_DEBUG(printf("days=%lld, rem=%lld\n", days, remainder););
  59 
  60         if (ts >= 0) {
  61                 tmp_days = days + 1;
  62 
  63                 if (tmp_days >= DAYS_PER_LYEAR_PERIOD || tmp_days <= -DAYS_PER_LYEAR_PERIOD) {
  64                         cur_year += YEARS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD);
  65                         tmp_days -= DAYS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD);
  66                 }
  67 
  68                 while (tmp_days >= DAYS_PER_LYEAR) {
  69                         cur_year++;
  70                         if (timelib_is_leap(cur_year)) {
  71                                 tmp_days -= DAYS_PER_LYEAR;
  72                         } else {
  73                                 tmp_days -= DAYS_PER_YEAR;
  74                         }
  75                 }
  76         } else {
  77                 tmp_days = days;
  78 
  79                 /* Guess why this might be for, it has to do with a pope ;-). It's also
  80                  * only valid for Great Brittain and it's colonies. It needs fixing for
  81                  * other locales. *sigh*, why is this crap so complex! */
  82                 /*
  83                 if (ts <= TIMELIB_LL_CONST(-6857352000)) {
  84                         tmp_days -= 11;
  85                 }
  86                 */
  87 
  88                 while (tmp_days <= 0) {
  89                         if (tmp_days < -1460970) {
  90                                 cur_year -= 4000;
  91                                 TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
  92                                 tmp_days += 1460970;
  93                         } else {
  94                                 cur_year--;
  95                                 TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
  96                                 if (timelib_is_leap(cur_year)) {
  97                                         tmp_days += DAYS_PER_LYEAR;
  98                                 } else {
  99                                         tmp_days += DAYS_PER_YEAR;
 100                                 }
 101                         }
 102                 }
 103                 remainder += SECS_PER_DAY;
 104         }
 105         TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
 106 
 107         months = timelib_is_leap(cur_year) ? month_tab_leap : month_tab;
 108         if (timelib_is_leap(cur_year) && cur_year < 1970) {
 109                 tmp_days--;
 110         }
 111         i = 11;
 112         while (i > 0) {
 113                 TIMELIB_DEBUG(printf("month=%lld (%d)\n", i, months[i]););
 114                 if (tmp_days > months[i]) {
 115                         break;
 116                 }
 117                 i--;
 118         }
 119         TIMELIB_DEBUG(printf("A: ts=%lld, year=%lld, month=%lld, day=%lld,", ts, cur_year, i + 1, tmp_days - months[i]););
 120 
 121         /* That was the date, now we do the tiiiime */
 122         hours = remainder / 3600;
 123         minutes = (remainder - hours * 3600) / 60;
 124         seconds = remainder % 60;
 125         TIMELIB_DEBUG(printf(" hour=%lld, minute=%lld, second=%lld\n", hours, minutes, seconds););
 126 
 127         tm->y = cur_year;
 128         tm->m = i + 1;
 129         tm->d = tmp_days - months[i];
 130         tm->h = hours;
 131         tm->i = minutes;
 132         tm->s = seconds;
 133         tm->z = 0;
 134         tm->dst = 0;
 135         tm->sse = ts;
 136         tm->sse_uptodate = 1;
 137         tm->tim_uptodate = 1;
 138         tm->is_localtime = 0;
 139 }
 140 
 141 void timelib_update_from_sse(timelib_time *tm)
 142 {
 143         timelib_sll sse;
 144         int z = tm->z;
 145         signed int dst = tm->dst;
 146 
 147         sse = tm->sse;
 148 
 149         switch (tm->zone_type) {
 150                 case TIMELIB_ZONETYPE_ABBR:
 151                 case TIMELIB_ZONETYPE_OFFSET: {
 152                         timelib_unixtime2gmt(tm, tm->sse - (tm->z * 60) + (tm->dst * 3600));
 153 
 154                         goto cleanup;
 155                 }
 156 
 157                 case TIMELIB_ZONETYPE_ID: {
 158                         timelib_time_offset *gmt_offset;
 159 
 160                         gmt_offset = timelib_get_time_zone_info(tm->sse, tm->tz_info);
 161                         timelib_unixtime2gmt(tm, tm->sse + gmt_offset->offset);
 162                         timelib_time_offset_dtor(gmt_offset);
 163 
 164                         goto cleanup;
 165                 }
 166 
 167                 default:
 168                         timelib_unixtime2gmt(tm, tm->sse);
 169                         goto cleanup;
 170         }
 171 cleanup:
 172         tm->sse = sse;
 173         tm->is_localtime = 1;
 174         tm->have_zone = 1;
 175         tm->z = z;
 176         tm->dst = dst;
 177 }
 178 
 179 void timelib_unixtime2local(timelib_time *tm, timelib_sll ts)
 180 {
 181         timelib_time_offset *gmt_offset;
 182         timelib_tzinfo      *tz = tm->tz_info;
 183 
 184         switch (tm->zone_type) {
 185                 case TIMELIB_ZONETYPE_ABBR:
 186                 case TIMELIB_ZONETYPE_OFFSET: {
 187                         int z = tm->z;
 188                         signed int dst = tm->dst;
 189 
 190                         timelib_unixtime2gmt(tm, ts - (tm->z * 60) + (tm->dst * 3600));
 191 
 192                         tm->z = z;
 193                         tm->dst = dst;
 194                         break;
 195                 }
 196 
 197                 case TIMELIB_ZONETYPE_ID:
 198                         gmt_offset = timelib_get_time_zone_info(ts, tz);
 199                         timelib_unixtime2gmt(tm, ts + gmt_offset->offset);
 200 
 201                         /* we need to reset the sse here as unixtime2gmt modifies it */
 202                         tm->sse = ts;
 203                         tm->dst = gmt_offset->is_dst;
 204                         tm->z = gmt_offset->offset;
 205                         tm->tz_info = tz;
 206 
 207                         timelib_time_tz_abbr_update(tm, gmt_offset->abbr);
 208                         timelib_time_offset_dtor(gmt_offset);
 209                         break;
 210 
 211                 default:
 212                         tm->is_localtime = 0;
 213                         tm->have_zone = 0;
 214                         return;
 215         }
 216 
 217         tm->is_localtime = 1;
 218         tm->have_zone = 1;
 219 }
 220 
 221 void timelib_set_timezone_from_offset(timelib_time *t, timelib_sll utc_offset)
 222 {
 223         if (t->tz_abbr) {
 224                 timelib_free(t->tz_abbr);
 225         }
 226         t->tz_abbr = NULL;
 227 
 228         t->z = utc_offset;
 229         t->have_zone = 1;
 230         t->zone_type = TIMELIB_ZONETYPE_OFFSET;
 231         t->dst = 0;
 232         t->tz_info = NULL;
 233 }
 234 
 235 void timelib_set_timezone_from_abbr(timelib_time *t, timelib_abbr_info abbr_info)
 236 {
 237         if (t->tz_abbr) {
 238                 timelib_free(t->tz_abbr);
 239         }
 240         t->tz_abbr = timelib_strdup(abbr_info.abbr);
 241 
 242         t->z = abbr_info.utc_offset;
 243         t->have_zone = 1;
 244         t->zone_type = TIMELIB_ZONETYPE_ABBR;
 245         t->dst = abbr_info.dst;
 246         t->tz_info = NULL;
 247 }
 248 
 249 void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz)
 250 {
 251         timelib_time_offset *gmt_offset;
 252 
 253         gmt_offset = timelib_get_time_zone_info(t->sse, tz);
 254         t->z = gmt_offset->offset;
 255 /*
 256         if (t->dst != gmt_offset->is_dst) {
 257                 printf("ERROR (%d, %d)\n", t->dst, gmt_offset->is_dst);
 258                 exit(1);
 259         }
 260 */
 261         t->dst = gmt_offset->is_dst;
 262         t->tz_info = tz;
 263         if (t->tz_abbr) {
 264                 timelib_free(t->tz_abbr);
 265         }
 266         t->tz_abbr = timelib_strdup(gmt_offset->abbr);
 267         timelib_time_offset_dtor(gmt_offset);
 268 
 269         t->have_zone = 1;
 270         t->zone_type = TIMELIB_ZONETYPE_ID;
 271 }
 272 
 273 /* Converts the time stored in the struct to localtime if localtime = true,
 274  * otherwise it converts it to gmttime. This is only done when necessary
 275  * ofcourse. */
 276 int timelib_apply_localtime(timelib_time *t, unsigned int localtime)
 277 {
 278         if (localtime) {
 279                 /* Converting from GMT time to local time */
 280                 TIMELIB_DEBUG(printf("Converting from GMT time to local time\n"););
 281 
 282                 /* Check if TZ is set */
 283                 if (!t->tz_info) {
 284                         TIMELIB_DEBUG(printf("E: No timezone configured, can't switch to local time\n"););
 285                         return -1;
 286                 }
 287 
 288                 timelib_unixtime2local(t, t->sse);
 289         } else {
 290                 /* Converting from local time to GMT time */
 291                 TIMELIB_DEBUG(printf("Converting from local time to GMT time\n"););
 292 
 293                 timelib_unixtime2gmt(t, t->sse);
 294         }
 295         return 0;
 296 }

/* [<][>][^][v][top][bottom][index][help] */