Back to index

php5  5.3.10
cdf_time.c
Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 2008 Christos Zoulas
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
00015  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00016  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00017  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
00018  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00019  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00020  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00021  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00022  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00023  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00024  * POSSIBILITY OF SUCH DAMAGE.
00025  */
00026 
00027 #include "file.h"
00028 
00029 #ifndef lint
00030 FILE_RCSID("@(#)$File: cdf_time.c,v 1.6 2009/03/10 11:44:29 christos Exp $")
00031 #endif
00032 
00033 #include <time.h>
00034 #ifdef TEST
00035 #include <err.h>
00036 #endif
00037 #include <string.h>
00038 
00039 #include "cdf.h"
00040 
00041 #define isleap(y) ((((y) % 4) == 0) && \
00042     ((((y) % 100) != 0) || (((y) % 400) == 0)))
00043 
00044 static const int mdays[] = {
00045     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
00046 };
00047 
00048 /*
00049  * Return the number of days between jan 01 1601 and jan 01 of year.
00050  */
00051 static int
00052 cdf_getdays(int year)
00053 {
00054        int days = 0;
00055        int y;
00056 
00057        for (y = CDF_BASE_YEAR; y < year; y++)
00058               days += isleap(y) + 365;
00059               
00060        return days;
00061 }
00062 
00063 /*
00064  * Return the day within the month
00065  */
00066 static int
00067 cdf_getday(int year, int days)
00068 {
00069        size_t m;
00070 
00071        for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) {
00072               int sub = mdays[m] + (m == 1 && isleap(year));
00073               if (days < sub)
00074                      return days;
00075               days -= sub;
00076        }
00077        return days;
00078 }
00079 
00080 /* 
00081  * Return the 0...11 month number.
00082  */
00083 static int
00084 cdf_getmonth(int year, int days)
00085 {
00086        size_t m;
00087 
00088        for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) {
00089               days -= mdays[m];
00090               if (m == 1 && isleap(year))
00091                      days--;
00092               if (days <= 0)
00093                      return (int)m;
00094        }
00095        return (int)m;
00096 }
00097 
00098 int
00099 cdf_timestamp_to_timespec(struct timeval *ts, cdf_timestamp_t t)
00100 {
00101        struct tm tm;
00102 #ifdef HAVE_STRUCT_TM_TM_ZONE
00103        static char UTC[] = "UTC";
00104 #endif
00105        int rdays;
00106 
00107        /* Time interval, in microseconds */
00108        ts->tv_usec = (t % CDF_TIME_PREC) * CDF_TIME_PREC;
00109 
00110        t /= CDF_TIME_PREC;
00111        tm.tm_sec = t % 60;
00112        t /= 60;
00113 
00114        tm.tm_min = t % 60;
00115        t /= 60;
00116 
00117        tm.tm_hour = t % 24;
00118        t /= 24;
00119 
00120        /* XXX: Approx */
00121        tm.tm_year = CDF_BASE_YEAR + (t / 365);
00122 
00123        rdays = cdf_getdays(tm.tm_year);
00124        t -= rdays;
00125        tm.tm_mday = cdf_getday(tm.tm_year, t);
00126        tm.tm_mon = cdf_getmonth(tm.tm_year, t);
00127        tm.tm_wday = 0;
00128        tm.tm_yday = 0;
00129        tm.tm_isdst = 0;
00130 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
00131        tm.tm_gmtoff = 0;
00132 #endif
00133 #ifdef HAVE_STRUCT_TM_TM_ZONE
00134        tm.tm_zone = UTC;
00135 #endif
00136        tm.tm_year -= 1900;
00137        ts->tv_sec = mktime(&tm);
00138        if (ts->tv_sec == -1) {
00139               errno = EINVAL;
00140               return -1;
00141        }
00142        return 0;
00143 }
00144 
00145 int
00146 cdf_timespec_to_timestamp(cdf_timestamp_t *t, const struct timeval *ts)
00147 {
00148        (void)&t;
00149        (void)&ts;
00150 #ifdef notyet
00151        struct tm tm;
00152        if (gmtime_r(&ts->ts_sec, &tm) == NULL) {
00153               errno = EINVAL;
00154               return -1;
00155        }
00156        *t = (ts->ts_usec / CDF_TIME_PREC) * CDF_TIME_PREC;
00157        *t = tm.tm_sec;
00158        *t += tm.tm_min * 60;
00159        *t += tm.tm_hour * 60 * 60;
00160        *t += tm.tm_mday * 60 * 60 * 24;
00161 #endif
00162        return 0;
00163 }
00164 
00165 
00166 #ifdef TEST
00167 int
00168 main(int argc, char *argv[])
00169 {
00170        struct timeval ts;
00171        static const cdf_timestamp_t tst = 0x01A5E403C2D59C00ULL;
00172        static const char *ref = "Sat Apr 23 01:30:00 1977";
00173        char *p, *q;
00174 
00175        cdf_timestamp_to_timespec(&ts, tst);
00176        p = ctime(&ts.tv_sec);
00177        if ((q = strchr(p, '\n')) != NULL)
00178               *q = '\0';
00179        if (strcmp(ref, p) != 0)
00180               errx(1, "Error date %s != %s\n", ref, p);
00181        return 0;
00182 }
00183 #endif