0
      0
  "   li~e8q2ʘoh      0
  *   lY>eJ}@?q1hu_I|+     /*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Derick Rethans
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "timelib.h"

#include <stdio.h>

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif

static int month_tab_leap[12] = { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
static int month_tab[12] =      { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };


/* Converts a Unix timestamp value into broken down time, in GMT */
void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)
{
	timelib_sll days, remainder, tmp_days;
	timelib_sll cur_year = 1970;
	timelib_sll i;
	timelib_sll hours, minutes, seconds;
	int *months;

	days = ts / SECS_PER_DAY;
	remainder = ts - (days * SECS_PER_DAY);
	if (ts < 0 && remainder == 0) {
		days++;
		remainder -= SECS_PER_DAY;
	}
	TIMELIB_DEBUG(printf("days=%lld, rem=%lld\n", days, remainder););

	if (ts >= 0) {
		tmp_days = days + 1;

		if (tmp_days >= DAYS_PER_LYEAR_PERIOD || tmp_days <= -DAYS_PER_LYEAR_PERIOD) {
			cur_year += YEARS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD);
			tmp_days -= DAYS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD);
		}

		while (tmp_days >= DAYS_PER_LYEAR) {
			cur_year++;
			if (timelib_is_leap(cur_year)) {
				tmp_days -= DAYS_PER_LYEAR;
			} else {
				tmp_days -= DAYS_PER_YEAR;
			}
		}
	} else {
		tmp_days = days;

		/* Guess why this might be for, it has to do with a pope ;-). It's also
		 * only valid for Great Brittain and it's colonies. It needs fixing for
		 * other locales. *sigh*, why is this crap so complex! */
		/*
		if (ts <= TIMELIB_LL_CONST(-6857352000)) {
			tmp_days -= 11;
		}
		*/

		while (tmp_days <= 0) {
			if (tmp_days < -1460970) {
				cur_year -= 4000;
				TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
				tmp_days += 1460970;
			} else {
				cur_year--;
				TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
				if (timelib_is_leap(cur_year)) {
					tmp_days += DAYS_PER_LYEAR;
				} else {
					tmp_days += DAYS_PER_YEAR;
				}
			}
		}
		remainder += SECS_PER_DAY;
	}
	TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););

	months = timelib_is_leap(cur_year) ? month_tab_leap : month_tab;
	if (timelib_is_leap(cur_year) && cur_year < 1970) {
		tmp_days--;
	}
	i = 11;
	while (i > 0) {
		TIMELIB_DEBUG(printf("month=%lld (%d)\n", i, months[i]););
		if (tmp_days > months[i]) {
			break;
		}
		i--;
	}
	TIMELIB_DEBUG(printf("A: ts=%lld, year=%lld, month=%lld, day=%lld,", ts, cur_year, i + 1, tmp_days - months[i]););

	/* That was the date, now we do the tiiiime */
	hours = remainder / 3600;
	minutes = (remainder - hours * 3600) / 60;
	seconds = remainder % 60;
	TIMELIB_DEBUG(printf(" hour=%lld, minute=%lld, second=%lld\n", hours, minutes, seconds););

	tm->y = cur_year;
	tm->m = i + 1;
	tm->d = tmp_days - months[i