1 /* 2 * COPYRIGHT: LGPL, See LGPL.txt in the top level directory 3 * PROJECT: ReactOS CRT library 4 * FILE: lib/sdk/crt/time/gmtime.c 5 * PURPOSE: Implementation of gmtime, _gmtime32, _gmtime64 6 * PROGRAMERS: Timo Kreuzer 7 */ 8 #include <precomp.h> 9 10 unsigned int g_monthdays[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; 11 unsigned int g_lpmonthdays[13] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; 12 13 struct tm * 14 _gmtime_worker(struct tm *ptm, __time64_t time, int do_dst) 15 { 16 unsigned int days, daystoyear, dayinyear, leapdays, leapyears, years, month; 17 unsigned int secondinday, secondinhour; 18 unsigned int *padays; 19 20 if (time < 0) 21 { 22 return 0; 23 } 24 25 /* Divide into date and time */ 26 days = (unsigned int)(time / SECONDSPERDAY); 27 secondinday = time % SECONDSPERDAY; 28 29 /* Shift to days from 1.1.1601 */ 30 days += DIFFDAYS; 31 32 /* Calculate leap days passed till today */ 33 leapdays = leapdays_passed(days); 34 35 /* Calculate number of full leap years passed */ 36 leapyears = leapyears_passed(days); 37 38 /* Are more leap days passed than leap years? */ 39 if (leapdays > leapyears) 40 { 41 /* Yes, we're in a leap year */ 42 padays = g_lpmonthdays; 43 } 44 else 45 { 46 /* No, normal year */ 47 padays = g_monthdays; 48 } 49 50 /* Calculate year */ 51 years = (days - leapdays) / 365; 52 ptm->tm_year = years - 299; 53 54 /* Calculate number of days till 1.1. of this year */ 55 daystoyear = years * 365 + leapyears; 56 57 /* Calculate the day in this year */ 58 dayinyear = days - daystoyear; 59 60 /* Shall we do DST corrections? */ 61 ptm->tm_isdst = 0; 62 if (do_dst) 63 { 64 int yeartime = dayinyear * SECONDSPERDAY + secondinday ; 65 if (yeartime >= dst_begin && yeartime <= dst_end) // FIXME! DST in winter 66 { 67 time -= _dstbias; 68 days = (unsigned int)(time / SECONDSPERDAY + DIFFDAYS); 69 dayinyear = days - daystoyear; 70 ptm->tm_isdst = 1; 71 } 72 } 73 74 ptm->tm_yday = dayinyear; 75 76 /* dayinyear < 366 => terminates with i <= 11 */ 77 for (month = 0; dayinyear >= padays[month+1]; month++) 78 ; 79 80 /* Set month and day in month */ 81 ptm->tm_mon = month; 82 ptm->tm_mday = 1 + dayinyear - padays[month]; 83 84 /* Get weekday */ 85 ptm->tm_wday = (days + 1) % 7; 86 87 /* Calculate hour and second in hour */ 88 ptm->tm_hour = secondinday / SECONDSPERHOUR; 89 secondinhour = secondinday % SECONDSPERHOUR; 90 91 /* Calculate minute and second */ 92 ptm->tm_min = secondinhour / 60; 93 ptm->tm_sec = secondinhour % 60; 94 95 return ptm; 96 } 97 98 /****************************************************************************** 99 * \name _gmtime64 100 * \brief 101 * \param ptime Pointer to a variable of type __time64_t containing the time. 102 */ 103 struct tm * 104 _gmtime64(const __time64_t * ptime) 105 { 106 thread_data_t *data = msvcrt_get_thread_data(); 107 108 /* Validate parameters */ 109 if (!ptime || *ptime < 0) 110 { 111 return NULL; 112 } 113 114 if(!data->time_buffer) 115 data->time_buffer = malloc(sizeof(struct tm)); 116 117 /* Use _gmtime_worker to do the real work */ 118 return _gmtime_worker(data->time_buffer, *ptime, 0); 119 } 120 121 errno_t 122 _gmtime64_s( 123 struct tm* ptm, 124 const __time64_t* ptime) 125 { 126 __time64_t time; 127 128 if (!ptm) 129 { 130 MSVCRT_INVALID_PMT("ptm == NULL", ERROR_BAD_COMMAND); 131 return ERROR_BAD_COMMAND; 132 } 133 134 if (!ptime) 135 { 136 MSVCRT_INVALID_PMT("ptime == NULL", ERROR_BAD_COMMAND); 137 return ERROR_BAD_COMMAND; 138 } 139 140 time = *ptime; 141 142 _gmtime_worker(ptm, time, 0); 143 144 return ERROR_SUCCESS; 145 } 146 147 /****************************************************************************** 148 * \name _gmtime32 149 * \brief 150 * \param ptime Pointer to a variable of type __time32_t containing the time. 151 */ 152 struct tm * 153 _gmtime32(const __time32_t * ptime) 154 { 155 __time64_t time64; 156 157 if (!ptime) 158 return NULL; 159 time64 = *ptime; 160 return _gmtime64(&time64); 161 } 162 163 errno_t 164 _gmtime32_s( 165 struct tm* ptm, 166 const __time32_t* ptime) 167 { 168 __time64_t time = *ptime; 169 if (!ptm) 170 { 171 MSVCRT_INVALID_PMT("ptm == NULL", ERROR_BAD_COMMAND); 172 return ERROR_BAD_COMMAND; 173 } 174 175 if (!ptime) 176 { 177 MSVCRT_INVALID_PMT("ptime == NULL", ERROR_BAD_COMMAND); 178 return ERROR_BAD_COMMAND; 179 } 180 181 _gmtime_worker(ptm, time, 0); 182 183 return ERROR_SUCCESS; 184 } 185 186 /****************************************************************************** 187 * \name gmtime 188 * \brief 189 * \param ptime Pointer to a variable of type time_t containing the time. 190 */ 191 struct tm * 192 gmtime(const time_t * ptime) 193 { 194 __time64_t time64; 195 196 if (!ptime) 197 return NULL; 198 time64 = *ptime; 199 return _gmtime64(&time64); 200 } 201