"Fossies" - the Fresh Open Source Software Archive

Member "apr-1.7.0/time/win32/time.c" (8 Sep 2018, 11231 Bytes) of package /linux/www/apr-1.7.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "time.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.6.5_vs_1.7.0.

    1 /* Licensed to the Apache Software Foundation (ASF) under one or more
    2  * contributor license agreements.  See the NOTICE file distributed with
    3  * this work for additional information regarding copyright ownership.
    4  * The ASF licenses this file to You under the Apache License, Version 2.0
    5  * (the "License"); you may not use this file except in compliance with
    6  * the License.  You may obtain a copy of the License at
    7  *
    8  *     http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 #include "apr_arch_atime.h"
   18 #include "apr_time.h"
   19 #include "apr_general.h"
   20 #include "apr_lib.h"
   21 #include "apr_portable.h"
   22 #if APR_HAVE_TIME_H
   23 #include <time.h>
   24 #endif
   25 #if APR_HAVE_ERRNO_H
   26 #include <errno.h>
   27 #endif
   28 #include <string.h>
   29 #include <winbase.h>
   30 #include "apr_arch_misc.h"
   31 
   32 /* Leap year is any year divisible by four, but not by 100 unless also
   33  * divisible by 400
   34  */
   35 #define IsLeapYear(y) ((!(y % 4)) ? (((y % 400) && !(y % 100)) ? 0 : 1) : 0)
   36 
   37 static DWORD get_local_timezone(TIME_ZONE_INFORMATION **tzresult)
   38 {
   39     static TIME_ZONE_INFORMATION tz;
   40     static DWORD result;
   41     static int init = 0;
   42 
   43     if (!init) {
   44         result = GetTimeZoneInformation(&tz);
   45         init = 1;
   46     }
   47 
   48     *tzresult = &tz;
   49     return result;
   50 }
   51 
   52 static void SystemTimeToAprExpTime(apr_time_exp_t *xt, SYSTEMTIME *tm)
   53 {
   54     static const int dayoffset[12] =
   55     {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
   56 
   57     /* Note; the caller is responsible for filling in detailed tm_usec,
   58      * tm_gmtoff and tm_isdst data when applicable.
   59      */
   60     xt->tm_usec = tm->wMilliseconds * 1000;
   61     xt->tm_sec  = tm->wSecond;
   62     xt->tm_min  = tm->wMinute;
   63     xt->tm_hour = tm->wHour;
   64     xt->tm_mday = tm->wDay;
   65     xt->tm_mon  = tm->wMonth - 1;
   66     xt->tm_year = tm->wYear - 1900;
   67     xt->tm_wday = tm->wDayOfWeek;
   68     xt->tm_yday = dayoffset[xt->tm_mon] + (tm->wDay - 1);
   69     xt->tm_isdst = 0;
   70     xt->tm_gmtoff = 0;
   71 
   72     /* If this is a leap year, and we're past the 28th of Feb. (the
   73      * 58th day after Jan. 1), we'll increment our tm_yday by one.
   74      */
   75     if (IsLeapYear(tm->wYear) && (xt->tm_yday > 58))
   76         xt->tm_yday++;
   77 }
   78 
   79 APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result, 
   80                                                     time_t input)
   81 {
   82     *result = (apr_time_t) input * APR_USEC_PER_SEC;
   83     return APR_SUCCESS;
   84 }
   85 
   86 /* Return micro-seconds since the Unix epoch (jan. 1, 1970) UTC */
   87 APR_DECLARE(apr_time_t) apr_time_now(void)
   88 {
   89     LONGLONG aprtime = 0;
   90     FILETIME time;
   91 #ifndef _WIN32_WCE
   92     GetSystemTimeAsFileTime(&time);
   93 #else
   94     SYSTEMTIME st;
   95     GetSystemTime(&st);
   96     SystemTimeToFileTime(&st, &time);
   97 #endif
   98     FileTimeToAprTime(&aprtime, &time);
   99     return aprtime; 
  100 }
  101 
  102 APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result,
  103                                            apr_time_t input)
  104 {
  105     FILETIME ft;
  106     SYSTEMTIME st;
  107     AprTimeToFileTime(&ft, input);
  108     FileTimeToSystemTime(&ft, &st);
  109     /* The Platform SDK documents that SYSTEMTIME/FILETIME are
  110      * generally UTC, so no timezone info needed
  111      * The time value makes a roundtrip, st cannot be invalid below.
  112      */
  113     SystemTimeToAprExpTime(result, &st);
  114     result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
  115     return APR_SUCCESS;
  116 }
  117 
  118 APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result, 
  119                                           apr_time_t input, 
  120                                           apr_int32_t offs)
  121 {
  122     FILETIME ft;
  123     SYSTEMTIME st;
  124     AprTimeToFileTime(&ft, input + (offs *  APR_USEC_PER_SEC));
  125     FileTimeToSystemTime(&ft, &st);
  126     /* The Platform SDK documents that SYSTEMTIME/FILETIME are
  127      * generally UTC, so we will simply note the offs used.
  128      * The time value makes a roundtrip, st cannot be invalid below.
  129      */
  130     SystemTimeToAprExpTime(result, &st);
  131     result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
  132     result->tm_gmtoff = offs;
  133     return APR_SUCCESS;
  134 }
  135 
  136 APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result,
  137                                           apr_time_t input)
  138 {
  139     SYSTEMTIME st;
  140     FILETIME ft, localft;
  141 
  142     AprTimeToFileTime(&ft, input);
  143 
  144 #if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE)
  145     IF_WIN_OS_IS_UNICODE
  146     {
  147         TIME_ZONE_INFORMATION *tz;
  148         SYSTEMTIME localst;
  149         apr_time_t localtime;
  150 
  151         get_local_timezone(&tz);
  152 
  153         FileTimeToSystemTime(&ft, &st);
  154 
  155         /* The Platform SDK documents that SYSTEMTIME/FILETIME are
  156          * generally UTC.  We use SystemTimeToTzSpecificLocalTime
  157          * because FileTimeToLocalFileFime is documented that the
  158          * resulting time local file time would have DST relative
  159          * to the *present* date, not the date converted.
  160          * The time value makes a roundtrip, localst cannot be invalid below.
  161          */
  162         SystemTimeToTzSpecificLocalTime(tz, &st, &localst);
  163         SystemTimeToAprExpTime(result, &localst);
  164         result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
  165 
  166 
  167         /* Recover the resulting time as an apr time and use the
  168          * delta for gmtoff in seconds (and ignore msec rounding) 
  169          */
  170         SystemTimeToFileTime(&localst, &localft);
  171         FileTimeToAprTime(&localtime, &localft);
  172         result->tm_gmtoff = (int)apr_time_sec(localtime) 
  173                           - (int)apr_time_sec(input);
  174 
  175         /* To compute the dst flag, we compare the expected 
  176          * local (standard) timezone bias to the delta.
  177          * [Note, in war time or double daylight time the
  178          * resulting tm_isdst is, desireably, 2 hours]
  179          */
  180         result->tm_isdst = (result->tm_gmtoff / 3600)
  181                          - (-(tz->Bias + tz->StandardBias) / 60);
  182     }
  183 #endif
  184 #if APR_HAS_ANSI_FS || defined(_WIN32_WCE)
  185     ELSE_WIN_OS_IS_ANSI
  186     {
  187         TIME_ZONE_INFORMATION tz;
  188     /* XXX: This code is simply *wrong*.  The time converted will always
  189          * map to the *now current* status of daylight savings time.
  190          * The time value makes a roundtrip, st cannot be invalid below.
  191          */
  192 
  193         FileTimeToLocalFileTime(&ft, &localft);
  194         FileTimeToSystemTime(&localft, &st);
  195         SystemTimeToAprExpTime(result, &st);
  196         result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
  197 
  198         switch (GetTimeZoneInformation(&tz)) {
  199             case TIME_ZONE_ID_UNKNOWN:
  200                 result->tm_isdst = 0;
  201                 /* Bias = UTC - local time in minutes
  202                  * tm_gmtoff is seconds east of UTC
  203                  */
  204                 result->tm_gmtoff = tz.Bias * -60;
  205                 break;
  206             case TIME_ZONE_ID_STANDARD:
  207                 result->tm_isdst = 0;
  208                 result->tm_gmtoff = (tz.Bias + tz.StandardBias) * -60;
  209                 break;
  210             case TIME_ZONE_ID_DAYLIGHT:
  211                 result->tm_isdst = 1;
  212                 result->tm_gmtoff = (tz.Bias + tz.DaylightBias) * -60;
  213                 break;
  214             default:
  215                 /* noop */;
  216         }
  217     }
  218 #endif
  219 
  220     return APR_SUCCESS;
  221 }
  222 
  223 APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *t,
  224                                            apr_time_exp_t *xt)
  225 {
  226     apr_time_t year = xt->tm_year;
  227     apr_time_t days;
  228     static const int dayoffset[12] =
  229     {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
  230 
  231     /* shift new year to 1st March in order to make leap year calc easy */
  232 
  233     if (xt->tm_mon < 2)
  234         year--;
  235 
  236     /* Find number of days since 1st March 1900 (in the Gregorian calendar). */
  237 
  238     days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4;
  239     days += dayoffset[xt->tm_mon] + xt->tm_mday - 1;
  240     days -= 25508;              /* 1 jan 1970 is 25508 days since 1 mar 1900 */
  241 
  242     days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec;
  243 
  244     if (days < 0) {
  245         return APR_EBADDATE;
  246     }
  247     *t = days * APR_USEC_PER_SEC + xt->tm_usec;
  248     return APR_SUCCESS;
  249 }
  250 
  251 APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *t,
  252                                                apr_time_exp_t *xt)
  253 {
  254     apr_status_t status = apr_time_exp_get(t, xt);
  255     if (status == APR_SUCCESS)
  256         *t -= (apr_time_t) xt->tm_gmtoff * APR_USEC_PER_SEC;
  257     return status;
  258 }
  259 
  260 APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime,
  261                                               apr_time_t *aprtime)
  262 {
  263     /* TODO: Consider not passing in pointer to apr_time_t (e.g., call by value) */
  264     AprTimeToFileTime(*ostime, *aprtime);
  265     return APR_SUCCESS;
  266 }
  267 
  268 APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime, 
  269                                               apr_time_exp_t *aprexptime)
  270 {
  271     (*ostime)->wYear = aprexptime->tm_year + 1900;
  272     (*ostime)->wMonth = aprexptime->tm_mon + 1;
  273     (*ostime)->wDayOfWeek = aprexptime->tm_wday;
  274     (*ostime)->wDay = aprexptime->tm_mday;
  275     (*ostime)->wHour = aprexptime->tm_hour;
  276     (*ostime)->wMinute = aprexptime->tm_min;
  277     (*ostime)->wSecond = aprexptime->tm_sec;
  278     (*ostime)->wMilliseconds = aprexptime->tm_usec / 1000;
  279     return APR_SUCCESS;
  280 }
  281 
  282 APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime,
  283                                               apr_os_imp_time_t **ostime,
  284                                               apr_pool_t *cont)
  285 {
  286     /* XXX: sanity failure, what is file time, gmt or local ?
  287      */
  288     FileTimeToAprTime(aprtime, *ostime);
  289     return APR_SUCCESS;
  290 }
  291 
  292 APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime,
  293                                               apr_os_exp_time_t **ostime,
  294                                               apr_pool_t *cont)
  295 {
  296     /* The Platform SDK documents that SYSTEMTIME/FILETIME are
  297      * generally UTC, so no timezone info needed
  298      */
  299     if ((*ostime)->wMonth < 1 || (*ostime)->wMonth > 12)
  300         return APR_EBADDATE;
  301 
  302     SystemTimeToAprExpTime(aprtime, *ostime);
  303     return APR_SUCCESS;
  304 }
  305 
  306 APR_DECLARE(void) apr_sleep(apr_interval_time_t t)
  307 {
  308     /* One of the few sane situations for a cast, Sleep
  309      * is in ms, not us, and passed as a DWORD value
  310      */
  311     Sleep((DWORD)(t / 1000));
  312 }
  313 
  314 #if defined(_WIN32_WCE)
  315 /* A noop on WinCE, like Unix implementation */
  316 APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p)
  317 {
  318     return;
  319 }
  320 #else
  321 static apr_status_t clock_restore(void *unsetres)
  322 {
  323     ULONG newRes;
  324     SetTimerResolution((ULONG)(apr_ssize_t)unsetres, FALSE, &newRes);
  325     return APR_SUCCESS;
  326 }
  327 
  328 APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p)
  329 {
  330     ULONG newRes;
  331     /* Timer resolution is stated in 100ns units.  Note that TRUE requests the
  332      * new clock resolution, FALSE above releases the request.
  333      */
  334     if (SetTimerResolution(10000, TRUE, &newRes) == 0 /* STATUS_SUCCESS */) {
  335         /* register the cleanup... */
  336         apr_pool_cleanup_register(p, (void*)10000, clock_restore,
  337                                   apr_pool_cleanup_null);
  338     }
  339 }
  340 #endif