xref: /reactos/sdk/lib/ucrt/time/loctotime.cpp (revision 04e0dc4a)
1 //
2 // loctotime.cpp
3 //
4 //      Copyright (c) Microsoft Corporation.  All rights reserved.
5 //
6 // Defines the loctotime_t() family of functions, which convert a local time to
7 // the internal time format (one of the time_t types).
8 //
9 #include <corecrt_internal_time.h>
10 
11 
12 
13 // Converts a local time to a time_t value.  Returns the time_t value on success;
14 // returns a time_t with the value -1 and sets errno on failure.  The 'dstflag'
15 // is 1 for Daylight Time, 0 for Standard Time, and -1 if not specified.
16 template <typename TimeType>
common_loctotime_t(int yr,int const mo,int const dy,int const hr,int const mn,int const sc,int const dstflag)17 static TimeType __cdecl common_loctotime_t(
18     int       yr, // Zero-based
19     int const mo, // One-based
20     int const dy, // One-based
21     int const hr,
22     int const mn,
23     int const sc,
24     int const dstflag
25     ) throw()
26 {
27     typedef __crt_time_time_t_traits<TimeType> time_traits;
28 
29     static TimeType const invalid_time = static_cast<TimeType>(-1);
30 
31     // Adjust the absolute year to be an offset from the year 1900:
32     yr -= 1900;
33 
34     _VALIDATE_RETURN_NOEXC(yr >= _BASE_YEAR && yr <= time_traits::max_year, EINVAL, invalid_time)
35     _VALIDATE_RETURN_NOEXC(mo >= 1 && mo <= 12,                             EINVAL, invalid_time)
36     _VALIDATE_RETURN_NOEXC(__crt_time_is_day_valid(yr, mo - 1, dy),         EINVAL, invalid_time)
37     _VALIDATE_RETURN_NOEXC(hr >= 0 && hr <= 23,                             EINVAL, invalid_time)
38     _VALIDATE_RETURN_NOEXC(mn >= 0 && mn <= 59,                             EINVAL, invalid_time)
39     _VALIDATE_RETURN_NOEXC(sc >= 0 && sc <= 59,                             EINVAL, invalid_time)
40 
41     // Compute the number of elapsed days in the current year:
42     int elapsed_days_this_year = dy + _days[mo - 1];
43     if (__crt_time_is_leap_year(yr) && mo > 2)
44         ++elapsed_days_this_year;
45 
46     TimeType const elapsed_years = static_cast<TimeType>(yr) - _BASE_YEAR;
47     TimeType const elapsed_leap_years = static_cast<TimeType>(__crt_time_elapsed_leap_years(yr));
48 
49     // The number of elapsed days is the number of days in each completed year
50     // since the epoch, plus one day per leap year, plus the number of days
51     // elapsed so far this year:
52     TimeType const elapsed_days =
53         elapsed_years * 365 +
54         elapsed_leap_years +
55         elapsed_days_this_year;
56 
57     TimeType const elapsed_hours   = elapsed_days    * 24 + hr;
58     TimeType const elapsed_minutes = elapsed_hours   * 60 + mn;
59     TimeType const elapsed_seconds = elapsed_minutes * 60 + sc;
60 
61     // Account for the time zone:
62     __tzset();
63 
64     int  daylight = 0;
65     long dstbias  = 0;
66     long timezone = 0;
67     _ERRCHECK(_get_daylight(&daylight));
68     _ERRCHECK(_get_dstbias (&dstbias ));
69     _ERRCHECK(_get_timezone(&timezone));
70 
71     TimeType const timezone_adjusted_seconds = elapsed_seconds + timezone;
72 
73     // Determine whether we are in Daylight Savings Time and adjust:
74     TimeType const dst_adjusted_seconds = timezone_adjusted_seconds + dstbias;
75 
76     if (dstflag == 1)
77         return dst_adjusted_seconds;
78 
79     tm tm_value;
80     tm_value.tm_yday = elapsed_days_this_year;
81     tm_value.tm_year = yr;
82     tm_value.tm_mon  = mo - 1;
83     tm_value.tm_hour = hr;
84     tm_value.tm_min  = mn;
85     tm_value.tm_sec  = sc;
86     if (dstflag == -1 && daylight != 0 && _isindst(&tm_value))
87         return dst_adjusted_seconds;
88 
89     // Otherwise, we are not in Daylight Savings Time:
90     return timezone_adjusted_seconds;
91 }
92 
__loctotime32_t(int const yr,int const mo,int const dy,int const hr,int const mn,int const sc,int const dstflag)93 extern "C" __time32_t __cdecl __loctotime32_t(
94     int const yr,
95     int const mo,
96     int const dy,
97     int const hr,
98     int const mn,
99     int const sc,
100     int const dstflag
101     )
102 {
103     return common_loctotime_t<__time32_t>(yr, mo, dy, hr, mn, sc, dstflag);
104 }
105 
__loctotime64_t(int const yr,int const mo,int const dy,int const hr,int const mn,int const sc,int const dstflag)106 extern "C" __time64_t __cdecl __loctotime64_t(
107     int const yr,
108     int const mo,
109     int const dy,
110     int const hr,
111     int const mn,
112     int const sc,
113     int const dstflag
114     )
115 {
116     return common_loctotime_t<__time64_t>(yr, mo, dy, hr, mn, sc, dstflag);
117 }
118