| 207 | } |
| 208 | |
| 209 | struct tm* GmTimeR(const time_t* timer, struct tm* tmbuf) { |
| 210 | i64 time = static_cast<i64>(*timer); |
| 211 | tm* resut = tmbuf; |
| 212 | int dayClock; |
| 213 | ui32 daysRemaining; |
| 214 | bool isLeapYear; |
| 215 | |
| 216 | if (time >= TDayNoToYearLookupTable::MinTimestamp && time <= TDayNoToYearLookupTable::MaxTimestamp) |
| 217 | { |
| 218 | dayClock = static_cast<int>(time % SECONDS_PER_DAY); |
| 219 | daysRemaining = time / SECONDS_PER_DAY; |
| 220 | tmbuf->tm_wday = static_cast<int>((daysRemaining + 4) % 7); // Day 0 was a thursday |
| 221 | daysRemaining -= TDayNoToYearLookupTable::StartDays; |
| 222 | const int year = DAYS_TO_YEAR_LOOKUP.FindYear(daysRemaining); |
| 223 | isLeapYear = IsLeapYear(year); |
| 224 | tmbuf->tm_year = year - STRUCT_TM_BASE_YEAR; |
| 225 | } else { |
| 226 | i64 year = UNIX_TIME_BASE_YEAR; |
| 227 | |
| 228 | if (Y_UNLIKELY(time < 0)) { |
| 229 | const ui64 shift = (ui64)(-time - 1) / (static_cast<ui64>(FOUR_CENTURY_DAYS) * SECONDS_PER_DAY) + 1; |
| 230 | time += static_cast<i64>(shift * FOUR_CENTURY_DAYS * SECONDS_PER_DAY); |
| 231 | year -= static_cast<i64>(shift * FOUR_CENTURY_YEARS); |
| 232 | } |
| 233 | |
| 234 | dayClock = static_cast<int>(time % SECONDS_PER_DAY); |
| 235 | ui64 dayNo = (ui64)time / SECONDS_PER_DAY; |
| 236 | tmbuf->tm_wday = (dayNo + 4) % 7; // Day 0 was a thursday |
| 237 | |
| 238 | if (int shiftYears = (year - 1) % FOUR_CENTURY_YEARS; shiftYears != 0) { |
| 239 | if (shiftYears < 0) { |
| 240 | shiftYears += FOUR_CENTURY_YEARS; |
| 241 | } |
| 242 | year -= shiftYears; |
| 243 | dayNo += shiftYears * DAYS_IN_YEAR + LeapYearCount(shiftYears); |
| 244 | } |
| 245 | |
| 246 | if (Y_UNLIKELY(dayNo >= FOUR_CENTURY_DAYS)) { |
| 247 | year += FOUR_CENTURY_YEARS * (dayNo / FOUR_CENTURY_DAYS); |
| 248 | dayNo = dayNo % FOUR_CENTURY_DAYS; |
| 249 | } |
| 250 | |
| 251 | daysRemaining = dayNo; |
| 252 | const int yearDiff = FindYearWithin4Centuries(daysRemaining); |
| 253 | year += yearDiff; |
| 254 | isLeapYear = IsLeapYear(yearDiff + 1); |
| 255 | tmbuf->tm_year = static_cast<int>(year - STRUCT_TM_BASE_YEAR); |
| 256 | |
| 257 | // check year overflow |
| 258 | if (Y_UNLIKELY(year - STRUCT_TM_BASE_YEAR != tmbuf->tm_year)) { |
| 259 | resut = nullptr; |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | tmbuf->tm_sec = dayClock % 60; |
| 264 | tmbuf->tm_min = (dayClock % 3600) / 60; |
| 265 | tmbuf->tm_hour = dayClock / 3600; |
| 266 | |