/* timestamp.c generated by valac 0.56.19, the Vala compiler
 * generated from timestamp.vala, do not modify */

/* timestamp.vala
 *
 * Copyright © 2012 Collabora Ltd.
 *             By Siegfried-Angel Gevatter Pujals <siegfried@gevatter.com>
 * Copyright © 2010 Canonical, Ltd.
 *             By Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "zeitgeist-datamodel.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

/**
     * Convert a {@link GLib.TimeVal} to an amount of milliseconds since
     * the Unix Epoch
     *
     * @param timeval time to convert
     *
     * @return number of milliseconds since the Unix Epoch
     */
gint64
zeitgeist_timestamp_from_timeval (GTimeVal* timeval)
{
	gint64 m_seconds = 0LL;
	GTimeVal _tmp0_;
	GTimeVal _tmp1_;
	gint64 result;
	g_return_val_if_fail (timeval != NULL, -1LL);
	_tmp0_ = *timeval;
	m_seconds = ((gint64) _tmp0_.tv_sec) * 1000;
	_tmp1_ = *timeval;
	result = m_seconds + (((gint64) _tmp1_.tv_usec) / 1000);
	return result;
}

/**
     * Write a Zeitgeist timestamp to a {@link GLib.TimeVal} instance.
     * Note that Zeitgeist uses only a millisecond resolution, whereas
     * {@link GLib.TimeVal} has microsecond resolution. This means that
     * the lower three digits of @tv.tv_usec will always be 0.
     *
     * @param timestamp to convert
     *
     * @return the equivalent {@link GLib.TimeVal} instance.
     */
void
zeitgeist_timestamp_to_timeval (gint64 timestamp,
                                GTimeVal* result)
{
	GTimeVal timeval = {0};
	g_get_current_time (&timeval);
	timeval.tv_sec = (glong) (timestamp / 1000);
	timeval.tv_usec = (glong) ((timestamp % 1000) * 1000);
	*result = timeval;
	return;
}

/**
     * Return the current timestamp in milliseconds.
     *
     * @return the timestamp for the current system time, in milliseconds
     *         since the Unix Epoch
     */
gint64
zeitgeist_timestamp_from_now (void)
{
	gint64 result;
	result = g_get_real_time () / 1000;
	return result;
}

/**
     * Parse a timestamp from an ISO8601-encoded string.
     *
     * @param datetime a string containing an ISO8601-conforming datetime
     *
     * @return the timestamp represented by the given string, or -1 if
     *         it can't be parsed
     */
gint64
zeitgeist_timestamp_from_iso8601 (const gchar* datetime)
{
	GTimeVal timeval = {0};
	gint64 result;
	g_return_val_if_fail (datetime != NULL, -1LL);
	g_get_current_time (&timeval);
	if (g_time_val_from_iso8601 (datetime, &timeval)) {
		GTimeVal _tmp0_;
		_tmp0_ = timeval;
		result = zeitgeist_timestamp_from_timeval (&_tmp0_);
		return result;
	} else {
		result = (gint64) -1;
		return result;
	}
}

/**
     * Convert a timestamp to a human-readable ISO8601 format
     *
     * @param timestamp a timestamp in milliseconds since the Unix Epoch
     *
     * @return a newly allocated string containing the ISO8601 version of
     *         the given timestamp
     */
gchar*
zeitgeist_timestamp_to_iso8601 (gint64 timestamp)
{
	GTimeVal timeval = {0};
	GTimeVal _tmp0_ = {0};
	gchar* _tmp1_;
	gchar* result;
	zeitgeist_timestamp_to_timeval (timestamp, &_tmp0_);
	timeval = _tmp0_;
	_tmp1_ = g_time_val_to_iso8601 (&timeval);
	result = _tmp1_;
	return result;
}

/**
     * Convert a ''GDate'' to a Zeitgeist timestamp
     *
     * @param date the date to convert
     *
     * @return the given date expressed as a timestamp in milliseconds since
     *         the Epoch. The timestamp is guaranteed to be roudned off to the
     *         midnight of the given date.
     */
gint64
zeitgeist_timestamp_from_date (GDate* date)
{
	gint64 julian = 0LL;
	gint64 result;
	g_return_val_if_fail (date != NULL, -1LL);
	julian = (gint64) g_date_get_julian (date);
	result = zeitgeist_timestamp_prev_midnight ((julian * ZEITGEIST_TIMESTAMP_DAY) - (1969 * ZEITGEIST_TIMESTAMP_YEAR));
	return result;
}

/**
     * Convert a day, month, year tuple into a Zeitgeist timestamp
     *
     * @param day the day of the month
     * @param month the month of the year
     * @param year the year
     *
     * @return the given date (rounded off to the midnight), expressed as
     *         a timestamp in milliseconds since the Epoch, or -1 in case
     *         the provided parameters don't constitute a valid date.
     */
gint64
zeitgeist_timestamp_from_dmy (GDateDay day,
                              GDateMonth month,
                              GDateYear year)
{
	GDate date = {0};
	GDate _tmp0_;
	gint64 result;
	memset (&date, 0, sizeof (GDate));
	g_date_set_dmy (&date, day, (gint) month, year);
	_tmp0_ = date;
	result = zeitgeist_timestamp_from_date (&_tmp0_);
	return result;
}

/**
     * Write a timestamp to a {@link GLib.Date} structure
     *
     * @param timestamp to convert
     * @return {@link GLib.Date} initialized to the given timestamp
     */
void
zeitgeist_timestamp_to_date (gint64 timestamp,
                             GDate* result)
{
	GDate date = {0};
	GTimeVal timeval = {0};
	GTimeVal _tmp0_ = {0};
	GTimeVal _tmp1_;
	memset (&date, 0, sizeof (GDate));
	zeitgeist_timestamp_to_timeval (timestamp, &_tmp0_);
	timeval = _tmp0_;
	_tmp1_ = timeval;
	g_date_set_time_val (&date, &_tmp1_);
	*result = date;
	return;
}

/**
     * Calculate the timestamp for the next midnight after the given timestamp.
     *
     * If is is already midnight (down to the millisecond), this method will
     * return the value for the next midnight. In other words, you can call
     * this method recursively in order to iterate, forwards in time, over
     * midnights.
     *
     * @param timestamp the Zeitgeist timestamp to find the next midnight for
     *
     * @return the timestamp for the next midnight after the given timestamp
     */
gint64
zeitgeist_timestamp_next_midnight (gint64 timestamp)
{
	gint64 remainder = 0LL;
	gint64 result;
	remainder = timestamp % ZEITGEIST_TIMESTAMP_DAY;
	if (remainder == ((gint64) 0)) {
		result = timestamp + ZEITGEIST_TIMESTAMP_DAY;
		return result;
	} else {
		result = (timestamp - remainder) + ZEITGEIST_TIMESTAMP_DAY;
		return result;
	}
}

/**
     * Calculate the timestamp for the midnight just before the given
     * timestamp.
     *
     * If is is already midnight (down to the millisecond), this method will
     * return the value for the previous midnight. In other words, you can
     * call this method recursively in order to iterate, backwards in time,
     * over midnights.
     *
     * @param timestamp the Zeitgeist timestamp to find the previous
     *        midnight for
     *
     * @return the timestamp for the midnight just before the given timestamp
     */
gint64
zeitgeist_timestamp_prev_midnight (gint64 timestamp)
{
	gint64 remainder = 0LL;
	gint64 result;
	remainder = timestamp % ZEITGEIST_TIMESTAMP_DAY;
	if (remainder == ((gint64) 0)) {
		result = timestamp - ZEITGEIST_TIMESTAMP_DAY;
		return result;
	} else {
		result = timestamp - remainder;
		return result;
	}
}

