__PREFIX_BEGIN__
//-----------------------------------------------------------------------------
// Copyright © 2004 - Philip Howard - All rights reserved
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// 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 General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//-----------------------------------------------------------------------------
// package	libh/time
// homepage	http://libh.slashusr.org/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// file		time.h
//-----------------------------------------------------------------------------
#ifndef __TIME_H__
#define __TIME_H__

__PREFIX_END__

__INCLUDE_BEGIN__
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>

#include <libh/div.h>
#include <libh/ctools.h>

__INCLUDE_END__

__DEFINE_BEGIN__
//-----------------------------------------------------------------------------
// type		JD, LJD
//
// purpose	Define a type for a Julian Date value as used in astronomy.
//		Type LJD is a greater precision version of JD.  It is used
//		in some intermediate calculations for less rounding effect.
//-----------------------------------------------------------------------------
typedef double				JD		;
typedef long double			LJD		;


//-----------------------------------------------------------------------------
// type		eday_t
//
// purpose	Define a timekeeping data type called Earth Day.
//
// resolution	1 day
//
// epoch	Monday 24 November 4714 BC Gregorian, 00:00:00
//		Monday 1 January 4713 BC Julian, 00:00:00
//-----------------------------------------------------------------------------
typedef int32_t				eday_t		;

#define EDAY_C(c)			(INT32_C(c))
#define EDAY_MIN			(INT32_MIN)
#define EDAY_MAX			(INT32_MAX)
#define EDAY_ERROR			(INT32_MAX)

//-----------------------------------------------------------------------------
// Define macros to add/subtract intervals of time to/from type etime_t.
//-----------------------------------------------------------------------------
#define eday_add_days(t,d)		((t)+(eday_t)(d))

#define eday_sub_days(t,d)		((t)-(eday_t)(d))

//-----------------------------------------------------------------------------
// Define macros to get the difference between two etime_t values and return
// the result in a specific relative scale.
//-----------------------------------------------------------------------------
#define eday_diff_days(a,b)		((b)-(a))

//-----------------------------------------------------------------------------
// Define special reference dates as EDAY values.
//-----------------------------------------------------------------------------
// The dates refer to the Gregorian proleptic calendar except those that end
// with "_JULIAN" which instead refer to the Julian proleptic calendar.
//-----------------------------------------------------------------------------
#define EDAY_23_NOV_4714_BC		EDAY_C(-1)
#define EDAY_31_DEC_4714_BC_JULIAN	EDAY_C(-1)
#define EDAY_24_NOV_4714_BC		EDAY_C(0)
#define EDAY_1_JAN_4713_BC_JULIAN	EDAY_C(0)
#define EDAY_25_NOV_4714_BC		EDAY_C(1)
#define EDAY_2_JAN_4713_BC_JULIAN	EDAY_C(1)

#define EDAY_30_DEC_2_BC		EDAY_C(1721058)
#define EDAY_1_JAN_1_BC_JULIAN		EDAY_C(1721058)
#define EDAY_1_JAN_0_JULIAN		EDAY_C(1721058)
#define EDAY_1_JAN_1_BC			EDAY_C(1721060)
#define EDAY_3_JAN_1_BC_JULIAN		EDAY_C(1721060)
#define EDAY_1_JAN_0			EDAY_C(1721060)
#define EDAY_3_JAN_0_JULIAN		EDAY_C(1721060)
#define EDAY_30_DEC_1_BC		EDAY_C(1721424)
#define EDAY_1_JAN_1_JULIAN		EDAY_C(1721424)
#define EDAY_1_JAN_1			EDAY_C(1721426)
#define EDAY_3_JAN_1_JULIAN		EDAY_C(1721426)

#define EDAY_14_SEP_763_JULIAN		EDAY_C(2000000)
#define EDAY_18_SEP_763			EDAY_C(2000000)
#define EDAY_27_JUN_1037_JULIAN		EDAY_C(2100000)
#define EDAY_3_JUL_1037			EDAY_C(2100000)
#define EDAY_4_OCT_1582_JULIAN		EDAY_C(2299160)
#define EDAY_14_OCT_1582		EDAY_C(2299160)
#define EDAY_30_DEC_1615_JULIAN		EDAY_C(2311300)
#define EDAY_9_JAN_1616			EDAY_C(2311300)

#define EDAY_16_NOV_1858		EDAY_C(2400000)
#define EDAY_1_JAN_1970			EDAY_C(2440588)
#define EDAY_1_JAN_1980			EDAY_C(2444240)
#define EDAY_1_JAN_2000			EDAY_C(2451545)
#define EDAY_1_JAN_2001			EDAY_C(2451911)
#define EDAY_1_JAN_2100			EDAY_C(2488070)
#define EDAY_1_JAN_2101			EDAY_C(2488435)
#define EDAY_31_AUG_2132		EDAY_C(2500000)
#define EDAY_1_JAN_2400			EDAY_C(2597642)
#define EDAY_1_JAN_2401			EDAY_C(2598008)
#define EDAY_14_AUG_3501		EDAY_C(2999999)
#define EDAY_15_AUG_3501		EDAY_C(3000000)
#define EDAY_10_SEP_4320		EDAY_C(3299160)

#define EDAY_1_JAN_10000		EDAY_C(5373485)
#define EDAY_20_DEC_22666		EDAY_C(10000000)
#define EDAY_20_AUG_26976		EDAY_C(11574074)
#define EDAY_7_AUG_269078		EDAY_C(100000000)
#define EDAY_3_DEC_287564		EDAY_C(106751991)

#define EDAY_UNIX_EPOCH			EDAY_1_JAN_1970
#define EDAY_DOS_EPOCH			EDAY_1_JAN_1980
#define EDAY_SYSTEM_EPOCH		EDAY_UNIX_EPOCH

//-----------------------------------------------------------------------------
// Express the minimum and maximum times for time_t in terms of eday_t.
//-----------------------------------------------------------------------------
#define EDAY_SYSTEM_MIN			(EDAY_SYSTEM_EPOCH+((eday_t)TIME_MIN/EDAY_C(86400)))
#define EDAY_SYSTEM_MAX			(EDAY_SYSTEM_EPOCH+((eday_t)TIME_MAX/EDAY_C(86400)))


//-----------------------------------------------------------------------------
// type		etime_t
//
// purpose	Define a timekeeping data type called Earth Time.
//
// resolution	1 microsecond
//
// epoch	00:00:00.000000 Monday 24 November 4714 BC
//
// earliest	00:00:00.000000 Monday 24 November 4714 BC
// latest	04:00:54.775807 Thursday 3 December 287564
//-----------------------------------------------------------------------------
typedef uint64_t			etime_t		;

#define etime_quo(x,y)			(((etime_t)(x))/((etime_t)(y)))
#define etime_mod(x,y)			(((etime_t)(x))%((etime_t)(y)))

#define ETIME_C(c)			(UINT64_C(c))
#define ETIME_MIN			(UINT64_C(0))
#define ETIME_MAX			(INT64_MAX)
#define ETIME_ERROR			(UINT64_MAX)

#define EDAY_ETIME_MIN			(etime_to_eday(ETIME_MIN))
#define EDAY_ETIME_MAX			(etime_to_eday(ETIME_MAX))

#define eday_too_lo_for_etime(e)	((e)<EDAY_ETIME_MIN)
#define eday_too_hi_for_etime(e)	((e)>EDAY_ETIME_MAX)

//-----------------------------------------------------------------------------
// Define special reference dates as ETIME values.
//-----------------------------------------------------------------------------
// The dates refer to the Gregorian proleptic calendar except those that end
// with "_JULIAN" which instead refer to the Julian proleptic calendar.
//-----------------------------------------------------------------------------
#define ETIME_23_NOV_4714_BC		ETIME_C(-86400000000)
#define ETIME_31_DEC_4714_BC_JULIAN	ETIME_C(-86400000000)
#define ETIME_24_NOV_4714_BC		ETIME_C(0)
#define ETIME_1_JAN_4713_BC_JULIAN	ETIME_C(0)
#define ETIME_25_NOV_4714_BC		ETIME_C(86400000000)
#define ETIME_2_JAN_4713_BC_JULIAN	ETIME_C(86400000000)

#define ETIME_30_DEC_2_BC		ETIME_C(148699411200000000)
#define ETIME_1_JAN_1_BC_JULIAN		ETIME_C(148699411200000000)
#define ETIME_1_JAN_0_JULIAN		ETIME_C(148699411200000000)
#define ETIME_1_JAN_1_BC		ETIME_C(148699584000000000)
#define ETIME_3_JAN_1_BC_JULIAN		ETIME_C(148699584000000000)
#define ETIME_1_JAN_0			ETIME_C(148699584000000000)
#define ETIME_3_JAN_0_JULIAN		ETIME_C(148699584000000000)
#define ETIME_30_DEC_1_BC		ETIME_C(148731033600000000)
#define ETIME_1_JAN_1_JULIAN		ETIME_C(148731033600000000)
#define ETIME_1_JAN_1			ETIME_C(148731206400000000)
#define ETIME_3_JAN_1_JULIAN		ETIME_C(148731206400000000)

#define ETIME_14_SEP_763_JULIAN		ETIME_C(172800000000000000)
#define ETIME_18_SEP_763		ETIME_C(172800000000000000)
#define ETIME_27_JUN_1037_JULIAN	ETIME_C(181440000000000000)
#define ETIME_3_JUL_1037		ETIME_C(181440000000000000)
#define ETIME_4_OCT_1582_JULIAN		ETIME_C(198647424000000000)
#define ETIME_14_OCT_1582		ETIME_C(198647424000000000)
#define ETIME_30_DEC_1615_JULIAN	ETIME_C(199696320000000000)
#define ETIME_9_JAN_1616		ETIME_C(199696320000000000)

#define ETIME_16_NOV_1858		ETIME_C(207360000000000000)
#define ETIME_1_JAN_1970		ETIME_C(210866803200000000)
#define ETIME_1_JAN_1980		ETIME_C(211182336000000000)
#define ETIME_1_JAN_2000		ETIME_C(211813488000000000)
#define ETIME_1_JAN_2001		ETIME_C(211845110400000000)
#define ETIME_1_JAN_2100		ETIME_C(214969248000000000)
#define ETIME_1_JAN_2101		ETIME_C(215000784000000000)
#define ETIME_31_AUG_2132		ETIME_C(216000000000000000)
#define ETIME_1_JAN_2400		ETIME_C(224436268800000000)
#define ETIME_1_JAN_2401		ETIME_C(224467891200000000)
#define ETIME_14_AUG_3501		ETIME_C(259199913600000000)
#define ETIME_15_AUG_3501		ETIME_C(259200000000000000)
#define ETIME_10_SEP_4320		ETIME_C(285047424000000000)

#define ETIME_1_JAN_10000		ETIME_C(464269104000000000)
#define ETIME_20_DEC_22666		ETIME_C(864000000000000000)
#define ETIME_20_AUG_26976		ETIME_C(1000000000000000000)
#define ETIME_7_AUG_269078		ETIME_C(8640000000000000000)
#define ETIME_3_DEC_287564		ETIME_C(9223372022400000000)

#define ETIME_UNIX_EPOCH		ETIME_1_JAN_1970
#define ETIME_DOS_EPOCH			ETIME_1_JAN_1980
#define ETIME_SYSTEM_EPOCH		ETIME_UNIX_EPOCH

//-----------------------------------------------------------------------------
// Express the minimum and maximum times for time_t in terms of etime_t.
//-----------------------------------------------------------------------------
#define ETIME_SYSTEM_MIN		(ETIME_SYSTEM_EPOCH+((etime_t)TIME_MIN*ETIME_C(1000000)))
#define ETIME_SYSTEM_MAX		(ETIME_SYSTEM_EPOCH+((etime_t)TIME_MAX*ETIME_C(1000000))+(ETIME_C(999999)))

//-----------------------------------------------------------------------------
// Define macros to extract time parts from type etime_t.
//-----------------------------------------------------------------------------
#define etime_get_hour_of_day(t)	(etime_mod((t),ETIME_C(86400000000))/ETIME_C(3600000000))
#define etime_get_min_of_day(t)		(etime_mod((t),ETIME_C(86400000000))/ETIME_C(60000000))
#define etime_get_sec_of_day(t)		(etime_mod((t),ETIME_C(86400000000))/ETIME_C(1000000))
#define etime_get_msec_of_day(t)	(etime_mod((t),ETIME_C(86400000000))/ETIME_C(1000))
#define etime_get_usec_of_day(t)	(etime_mod((t),ETIME_C(86400000000)))
#define etime_get_nsec_of_day(t)	(etime_mod((t),ETIME_C(86400000000))*ETIME_C(1000))

#define etime_get_min_of_hour(t)	(etime_mod((t),ETIME_C(3600000000))/ETIME_C(60000000))
#define etime_get_sec_of_hour(t)	(etime_mod((t),ETIME_C(3600000000))/ETIME_C(1000000))
#define etime_get_msec_of_hour(t)	(etime_mod((t),ETIME_C(3600000000))/ETIME_C(1000))
#define etime_get_usec_of_hour(t)	(etime_mod((t),ETIME_C(3600000000)))
#define etime_get_nsec_of_hour(t)	(etime_mod((t),ETIME_C(3600000000))*ETIME_C(1000))

#define etime_get_sec_of_min(t)		(etime_mod((t),ETIME_C(60000000))/ETIME_C(1000000))
#define etime_get_msec_of_min(t)	(etime_mod((t),ETIME_C(60000000))/ETIME_C(1000))
#define etime_get_usec_of_min(t)	(etime_mod((t),ETIME_C(60000000)))
#define etime_get_nsec_of_min(t)	(etime_mod((t),ETIME_C(60000000))*ETIME_C(1000))

#define etime_get_msec_of_sec(t)	(etime_mod((t),ETIME_C(1000000))/ETIME_C(1000))
#define etime_get_usec_of_sec(t)	(etime_mod((t),ETIME_C(1000000)))
#define etime_get_nsec_of_sec(t)	(etime_mod((t),ETIME_C(1000000))*ETIME_C(1000))

#define etime_get_usec_of_msec(t)	(etime_mod((t),ETIME_C(1000)))
#define etime_get_nsec_of_msec(t)	(etime_mod((t),ETIME_C(1000))*ETIME_C(1000))

#define etime_get_nsec_of_usec(t)	(0)

//-----------------------------------------------------------------------------
// Define macros to add/subtract intervals of time to/from type etime_t.
//-----------------------------------------------------------------------------
#define etime_add_days(t,d)		((t)+(long long)(d)*86400000000LL)
#define etime_add_hours(t,h)		((t)+(long long)(h)*3600000000LL)
#define etime_add_mins(t,m)		((t)+(long long)(m)*60000000LL)
#define etime_add_secs(t,s)		((t)+(long long)(s)*1000000LL)
#define etime_add_msecs(t,m)		((t)+(long long)(m)*1000LL)
#define etime_add_usecs(t,u)		((t)+(long long)(u))
#define etime_add_nsecs(t,n)		((t)+(long long)(n)/1000LL)

#define etime_sub_days(t,d)		((t)-(long long)(d)*86400000000LL)
#define etime_sub_hours(t,h)		((t)-(long long)(h)*3600000000LL)
#define etime_sub_mins(t,m)		((t)-(long long)(m)*60000000LL)
#define etime_sub_secs(t,s)		((t)-(long long)(s)*1000000LL)
#define etime_sub_msecs(t,m)		((t)-(long long)(m)*1000LL)
#define etime_sub_usecs(t,u)		((t)-(long long)(u))
#define etime_sub_nsecs(t,n)		((t)-(long long)(n)/1000LL)

//-----------------------------------------------------------------------------
// Define macros to get the difference between two etime_t values and return
// the result in a specific relative scale.
//-----------------------------------------------------------------------------
#define etime_diff_days(a,b)		(etime_quo((b),86400000000LL)-etime_quo((a),86400000000LL))
#define etime_diff_hours(a,b)		(etime_quo((b),3600000000LL)-etime_quo((a),3600000000LL))
#define etime_diff_mins(a,b)		(etime_quo((b),60000000LL)-etime_quo((a),60000000LL))
#define etime_diff_secs(a,b)		(etime_quo((b),1000000LL)-etime_quo((a),1000000LL))
#define etime_diff_msecs(a,b)		(etime_quo((b),1000L-etime_quo((a),1000L)))
#define etime_diff_usecs(a,b)		((b)-(a))
#define etime_diff_nsecs(a,b)		(((b)-(a))*1000LL)


//-----------------------------------------------------------------------------
// struct	ecal_t
//
// purpose	Combine calendar and time elements into one struct.
//
// note		This struct is similar to (struct tm) but includes
//		1.  a calendar type flag (defined by ECAL_TYPE_*)
//		2.  nanoseconds part of a second
//		3.  attoseconds part of a nanosecond
//-----------------------------------------------------------------------------
struct ecal_t {
    int		type		;
    int		isleap		;
    long int	year		;
    int		month		;
    int		yday		;
    int		mday		;
    int		wday		;
    int		week		;
    int		hour		;
    int		min		;
    int		sec		;
    long int	nsec		;
    long int	asec		;
};
typedef struct ecal_t		ecal_t		;

#define ECAL_ISLEAP_NOTSPEC	-1
#define ECAL_ISLEAP_NO		0
#define ECAL_ISLEAP_YES		1

#define ECAL_TYPE_NOTSPEC	0
#define ECAL_TYPE_JULIAN	1
#define ECAL_TYPE_GREGORIAN	2


//-----------------------------------------------------------------------------
// type		extime_t
//
// purpose	Define a timekeeping data type for extreme purposes.
//
// resolution	1 attosecond
//
// range	over 584 billion years
//
// epoch	00:00:00.000000 Monday 24 November 4714 BC
//-----------------------------------------------------------------------------
struct extime_t {
    int64_t	sec		;	// seconds since epoch
    int64_t	asec		;	// plus attoseconds
};
typedef struct extime_t		extime_t		;
typedef struct extime_t *	extime_p		;


//-----------------------------------------------------------------------------
// type		lday_t
//
// purpose	This is the type for a Lilian Day value.  The Lilian Day is
//		the number of days since the day before the Gregorian calendar
//		was first put into use (15 October 1582 Gregorian, which is
//		Lilian day 1).  It was created by Aloisius Lilius, advisor to
//		Pope Gregory XIII, and later proposed by IBM as an alternative
//		date representation for Y2K issues.
//
//		The LDAY format does not provide for distinction between dates
//		in this format when mixed with dates in common formats such as
//		DDMMYY as used in Europe.  The date 15 December 2001 will be
//		the value 151201 in DDMMYY format, but this same number in LDAY
//		format represents 4 October 1996.  So LDAY dates and DDMMYY or
//		MMDDYY cannot be intermixed.  For that capability, see the XDAY
//		format below.
//
//		At least 32 bits is needed.
//-----------------------------------------------------------------------------
typedef int32_t				lday_t		;

#define LDAY_C(c)			(INT32_C(c))
#define LDAY_ERROR			(INT32_MIN)
#define LDAY_MIN			(INT32_MIN+LDAY_C(1))
#define LDAY_MAX			(INT32_MAX)

//-----------------------------------------------------------------------------
// Define special reference dates as LDAY values.
//-----------------------------------------------------------------------------
// The dates refer to the Gregorian proleptic calendar except those that end
// with "_JULIAN" which instead refer to the Julian proleptic calendar.
//-----------------------------------------------------------------------------
#define LDAY_23_NOV_4714_BC		LDAY_C(-2299161)
#define LDAY_31_DEC_4714_BC_JULIAN	LDAY_C(-2299161)
#define LDAY_24_NOV_4714_BC		LDAY_C(-2299160)
#define LDAY_1_JAN_4713_BC_JULIAN	LDAY_C(-2299160)
#define LDAY_25_NOV_4714_BC		LDAY_C(-2299159)
#define LDAY_2_JAN_4713_BC_JULIAN	LDAY_C(-2299159)

#define LDAY_30_DEC_2_BC		LDAY_C(-578102)
#define LDAY_1_JAN_1_BC_JULIAN		LDAY_C(-578102)
#define LDAY_1_JAN_0_JULIAN		LDAY_C(-578102)
#define LDAY_1_JAN_1_BC			LDAY_C(-578100)
#define LDAY_3_JAN_1_BC_JULIAN		LDAY_C(-578100)
#define LDAY_1_JAN_0			LDAY_C(-578100)
#define LDAY_3_JAN_0_JULIAN		LDAY_C(-578100)
#define LDAY_30_DEC_1_BC		LDAY_C(-577736)
#define LDAY_1_JAN_1_JULIAN		LDAY_C(-577736)
#define LDAY_1_JAN_1			LDAY_C(-577734)
#define LDAY_3_JAN_1_JULIAN		LDAY_C(-577734)

#define LDAY_14_SEP_763_JULIAN		LDAY_C(-299160)
#define LDAY_18_SEP_763			LDAY_C(-299160)
#define LDAY_27_JUN_1037_JULIAN		LDAY_C(-199160)
#define LDAY_3_JUL_1037			LDAY_C(-199160)
#define LDAY_4_OCT_1582_JULIAN		LDAY_C(0)
#define LDAY_14_OCT_1582		LDAY_C(0)
#define LDAY_30_DEC_1615_JULIAN		LDAY_C(12140)
#define LDAY_9_JAN_1616			LDAY_C(12140)

#define LDAY_16_NOV_1858		LDAY_C(100840)
#define LDAY_1_JAN_1970			LDAY_C(141428)
#define LDAY_1_JAN_1980			LDAY_C(145080)
#define LDAY_1_JAN_2000			LDAY_C(152385)
#define LDAY_1_JAN_2001			LDAY_C(152751)
#define LDAY_1_JAN_2100			LDAY_C(188910)
#define LDAY_1_JAN_2101			LDAY_C(189275)
#define LDAY_31_AUG_2132		LDAY_C(200840)
#define LDAY_1_JAN_2400			LDAY_C(298482)
#define LDAY_1_JAN_2401			LDAY_C(298848)
#define LDAY_14_AUG_3501		LDAY_C(700839)
#define LDAY_15_AUG_3501		LDAY_C(700840)
#define LDAY_10_SEP_4320		LDAY_C(1000000)

#define LDAY_UNIX_EPOCH			LDAY_1_JAN_1970
#define LDAY_DOS_EPOCH			LDAY_1_JAN_1980
#define LDAY_SYSTEM_EPOCH		LDAY_UNIX_EPOCH

//-----------------------------------------------------------------------------
// Express the minimum and maximum times for time_t in terms of lday_t.
//-----------------------------------------------------------------------------
#define LDAY_SYSTEM_MIN			(LDAY_SYSTEM_EPOCH+((lday_t)TIME_MIN/LDAY_C(86400)))
#define LDAY_SYSTEM_MAX			(LDAY_SYSTEM_EPOCH+((lday_t)TIME_MAX/LDAY_C(86400)))


//-----------------------------------------------------------------------------
// type		xday_t
//
// purpose	This is the type for an eXchange Day value.  The eXchange Day
//		is the Julian Date minus 1999999.5 (Earth Day minus 2000000) to
//		make 6 digits with a value distinguishable from any MMDDYY or
//		DDMMYY formatted dates, to provide a means to store dates in
//		existing 6 digit date fields while co-existing with unconverted
//		dates and detecting them appropriately.
//
//		Since the largest valid date stored in DDMMYY format would be
//		311299, the XDAY could be distinguished with a value of 311300
//		(9 Jan 1616 Gregorian) or greater.  Simpler testing of dates
//		stored as character digits can be used if XDAY is limited to
//		400000 (16 Nov 1858) which allows testing the first digit for
//		'4' or greater.  The XDAY format is useful for 6 digit date
//		fields until XDAY value 999999 (14 Aug 3501).
//
//		The eXchange Day was designed by Bob Bemer.
//
//		At least 32 bits is needed.
//-----------------------------------------------------------------------------
typedef int32_t				xday_t		;

#define XDAY_C(c)			(INT32_C(c))
#define XDAY_ERROR			(INT32_MIN)
#define XDAY_MIN			(INT32_MIN+XDAY_C(1))
#define XDAY_MAX			(INT32_MAX)

//-----------------------------------------------------------------------------
// Define special reference dates as XDAY values.
//-----------------------------------------------------------------------------
// The dates refer to the Gregorian proleptic calendar except those that end
// with "_JULIAN" which instead refer to the Julian proleptic calendar.
//-----------------------------------------------------------------------------
#define XDAY_23_NOV_4714_BC		XDAY_C(-2000001)
#define XDAY_31_DEC_4714_BC_JULIAN	XDAY_C(-2000001)
#define XDAY_24_NOV_4714_BC		XDAY_C(-2000000)
#define XDAY_1_JAN_4713_BC_JULIAN	XDAY_C(-2000000)
#define XDAY_25_NOV_4714_BC		XDAY_C(-1999999)
#define XDAY_2_JAN_4713_BC_JULIAN	XDAY_C(-1999999)

#define XDAY_30_DEC_2_BC		XDAY_C(-278942)
#define XDAY_1_JAN_1_BC_JULIAN		XDAY_C(-278942)
#define XDAY_1_JAN_0_JULIAN		XDAY_C(-278942)
#define XDAY_1_JAN_1_BC			XDAY_C(-278940)
#define XDAY_3_JAN_1_BC_JULIAN		XDAY_C(-278940)
#define XDAY_1_JAN_0			XDAY_C(-278940)
#define XDAY_3_JAN_0_JULIAN		XDAY_C(-278940)
#define XDAY_30_DEC_1_BC		XDAY_C(-278576)
#define XDAY_1_JAN_1_JULIAN		XDAY_C(-278576)
#define XDAY_1_JAN_1			XDAY_C(-278574)
#define XDAY_3_JAN_1_JULIAN		XDAY_C(-278574)

#define XDAY_14_SEP_763_JULIAN		XDAY_C(0)
#define XDAY_18_SEP_763			XDAY_C(0)
#define XDAY_27_JUN_1037_JULIAN		XDAY_C(100000)
#define XDAY_3_JUL_1037			XDAY_C(100000)
#define XDAY_4_OCT_1582_JULIAN		XDAY_C(299160)
#define XDAY_14_OCT_1582		XDAY_C(299160)
#define XDAY_30_DEC_1615_JULIAN		XDAY_C(311300)
#define XDAY_9_JAN_1616			XDAY_C(311300)

#define XDAY_16_NOV_1858		XDAY_C(400000)
#define XDAY_1_JAN_1970			XDAY_C(440588)
#define XDAY_1_JAN_1980			XDAY_C(444240)
#define XDAY_1_JAN_2000			XDAY_C(451545)
#define XDAY_1_JAN_2001			XDAY_C(451911)
#define XDAY_1_JAN_2100			XDAY_C(488070)
#define XDAY_1_JAN_2101			XDAY_C(488435)
#define XDAY_31_AUG_2132		XDAY_C(500000)
#define XDAY_1_JAN_2400			XDAY_C(597642)
#define XDAY_1_JAN_2401			XDAY_C(598008)
#define XDAY_14_AUG_3501		XDAY_C(999999)
#define XDAY_15_AUG_3501		XDAY_C(1000000)

#define XDAY_UNIX_EPOCH			XDAY_1_JAN_1970
#define XDAY_DOS_EPOCH			XDAY_1_JAN_1980
#define XDAY_SYSTEM_EPOCH		XDAY_UNIX_EPOCH

//-----------------------------------------------------------------------------
// Express the minimum and maximum times for time_t in terms of xday_t.
//-----------------------------------------------------------------------------
#define XDAY_SYSTEM_MIN			(XDAY_SYSTEM_EPOCH+((xday_t)TIME_MIN/XDAY_C(86400)))
#define XDAY_SYSTEM_MAX			(XDAY_SYSTEM_EPOCH+((xday_t)TIME_MAX/XDAY_C(86400)))


//-----------------------------------------------------------------------------
// typedef	time_t (not actually defined here)
//
// purpose	Number of seconds since host epoch, generally in 32 bits,
//		with negative values representing time before the epoch.
//
// note		UNIX uses an epoch of 1970-01-01.00:00:00
//		There is currently no support for other host epochs.
//-----------------------------------------------------------------------------
#if 0
#define TIME_MIN			(((time_t)1)<<(((sizeof(time_t))*(CHAR_BIT))-1))
#define TIME_MAX			(~(((time_t)1)<<(((sizeof(time_t))*(CHAR_BIT))-1)))
#else
#define TIME_MIN			int_min(time_t)
#define TIME_MAX			int_max(time_t)
#endif

//-----------------------------------------------------------------------------
// Define macros to extract time parts from type time_t.
//-----------------------------------------------------------------------------
#define time_get_hour_of_day(t)		(mod_ni((t),TIME_C(86400))/TIME_C(3600))
#define time_get_min_of_day(t)		(mod_ni((t),TIME_C(86400))/TIME_C(60))
#define time_get_sec_of_day(t)		(mod_ni((t),TIME_C(86400)))

#define time_get_min_of_hour(t)		(mod_ni((t),TIME_C(3600))/TIME_C(60))
#define time_get_sec_of_hour(t)		(mod_ni((t),TIME_C(3600)))

#define time_get_sec_of_min(t)		(mod_ni((t),TIME_C(60)))

//-----------------------------------------------------------------------------
// Define macros to add/subtract intervals of time to/from type time_t.
//-----------------------------------------------------------------------------
#define time_add_days(t,d)		((t)+(long long)(d)*86400LL)
#define time_add_hours(t,h)		((t)+(long long)(h)*3600LL)
#define time_add_mins(t,m)		((t)+(long long)(m)*60LL)
#define time_add_secs(t,s)		((t)+(long long)(s))
#define time_add_msecs(t,m)		((t)+(long long)(m)/1000LL)
#define time_add_usecs(t,u)		((t)+(long long)(u)/1000000LL)
#define time_add_nsecs(t,n)		((t)+(long long)(n)/1000000000LL)

#define time_sub_days(t,d)		((t)-(long long)(d)*86400LL)
#define time_sub_hours(t,h)		((t)-(long long)(h)*3600LL)
#define time_sub_mins(t,m)		((t)-(long long)(m)*60LL)
#define time_sub_secs(t,s)		((t)-(long long)(s))
#define time_sub_msecs(t,m)		((t)-(long long)(m)/1000LL)
#define time_sub_usecs(t,u)		((t)-(long long)(u)/1000000LL)
#define time_sub_nsecs(t,n)		((t)-(long long)(n)/1000000000LL)

//-----------------------------------------------------------------------------
// Define macros to get the difference between two time_t values and return
// the result in a specific relative scale.
//-----------------------------------------------------------------------------
#define time_diff_days(a,b)		(quo_ni((b),86400LL)-quo_ni((a),86400LL))
#define time_diff_hours(a,b)		(quo_ni((b),3600LL)-quo_ni((a),3600LL))
#define time_diff_mins(a,b)		(quo_ni((b),60LL)-quo_ni((a),60LL))
#define time_diff_secs(a,b)		((b)-(a))
#define time_diff_msecs(a,b)		(((b)-(a))*1000LL)
#define time_diff_usecs(a,b)		(((b)-(a))*1000000LL)
#define time_diff_nsecs(a,b)		(((b)-(a))*1000000000LL)


//-----------------------------------------------------------------------------
// typedef	time64_t
//
// purpose	Number of seconds since host epoch, in at least 64 bits,
//		with negative values representing time before the epoch.
//
// note		UNIX uses an epoch of 1970-01-01.00:00:00
//		There is currently no support for other host epochs.
//
// note		This type is provided as a means for programs that need to use
//		64 bits for a time measured in seconds to do so regardless of
//		the size the system defines for time_t.
//-----------------------------------------------------------------------------
typedef int64_t				time64_t	;

#define TIME64_C(c)			(INT64_C(c))
#define TIME64_ERROR			(INT64_MIN)
#define TIME64_MIN			(INT64_MIN+TIME64_C(1))
#define	TIME64_MAX			(INT64_MAX)

//-----------------------------------------------------------------------------
// Define macros to extract time parts from type time64_t.
//-----------------------------------------------------------------------------
#define time64_get_hour_of_day(t)	(mod_ni((t),TIME64_C(86400))/TIME64_C(3600))
#define time64_get_min_of_day(t)	(mod_ni((t),TIME64_C(86400))/TIME64_C(60))
#define time64_get_sec_of_day(t)	(mod_ni((t),TIME64_C(86400)))
#define time64_get_msec_of_day(t)	(mod_ni((t),TIME64_C(86400))*TIME64_C(1000))
#define time64_get_usec_of_day(t)	(mod_ni((t),TIME64_C(86400))*TIME64_C(1000000))
#define time64_get_nsec_of_day(t)	(mod_ni((t),TIME64_C(86400))*TIME64_C(1000000000))

#define time64_get_min_of_hour(t)	(mod_ni((t),TIME64_C(3600))/TIME64_C(60))
#define time64_get_sec_of_hour(t)	(mod_ni((t),TIME64_C(3600)))
#define time64_get_msec_of_hour(t)	(mod_ni((t),TIME64_C(3600))*TIME64_C(1000))
#define time64_get_usec_of_hour(t)	(mod_ni((t),TIME64_C(3600))*TIME64_C(1000000))
#define time64_get_nsec_of_hour(t)	(mod_ni((t),TIME64_C(3600))*TIME64_C(1000000000))

#define time64_get_sec_of_min(t)	(mod_ni((t),TIME64_C(60)))
#define time64_get_msec_of_min(t)	(mod_ni((t),TIME64_C(60))*TIME64_C(1000))
#define time64_get_usec_of_min(t)	(mod_ni((t),TIME64_C(60))*TIME64_C(1000000))
#define time64_get_nsec_of_min(t)	(mod_ni((t),TIME64_C(60))*TIME64_C(1000000000))

#define time64_get_msec_of_sec(t)	(0)
#define time64_get_usec_of_sec(t)	(0)
#define time64_get_nsec_of_sec(t)	(0)

#define time64_get_usec_of_msec(t)	(0)
#define time64_get_nsec_of_msec(t)	(0)

#define time64_get_nsec_of_usec(t)	(0)

//-----------------------------------------------------------------------------
// Define macros to add/subtract intervals of time to/from type time64_t.
//-----------------------------------------------------------------------------
#define time64_add_days(t,d)		((t)+(long long)(d)*86400LL)
#define time64_add_hours(t,h)		((t)+(long long)(h)*3600LL)
#define time64_add_mins(t,m)		((t)+(long long)(m)*60LL)
#define time64_add_secs(t,s)		((t)+(long long)(s))
#define time64_add_msecs(t,m)		((t)+(long long)(m)/1000LL)
#define time64_add_usecs(t,u)		((t)+(long long)(u)/1000000LL)
#define time64_add_nsecs(t,n)		((t)+(long long)(n)/1000000000LL)

#define time64_sub_days(t,d)		((t)-(long long)(d)*86400LL)
#define time64_sub_hours(t,h)		((t)-(long long)(h)*3600LL)
#define time64_sub_mins(t,m)		((t)-(long long)(m)*60LL)
#define time64_sub_secs(t,s)		((t)-(long long)(s))
#define time64_sub_msecs(t,m)		((t)-(long long)(m)/1000LL)
#define time64_sub_usecs(t,u)		((t)-(long long)(u)/1000000LL)
#define time64_sub_nsecs(t,n)		((t)-(long long)(n)/1000000000LL)

//-----------------------------------------------------------------------------
// Define macros to get the difference between two time64_t values and return
// the result in a specific relative scale.
//-----------------------------------------------------------------------------
#define time64_diff_days(a,b)		(quo_ni((b),86400LL)-quo_ni((a),86400LL))
#define time64_diff_hours(a,b)		(quo_ni((b),3600LL)-quo_ni((a),3600LL))
#define time64_diff_mins(a,b)		(quo_ni((b),60LL)-quo_ni((a),60LL))
#define time64_diff_secs(a,b)		((b)-(a))
#define time64_diff_msecs(a,b)		(((b)-(a))*1000LL)
#define time64_diff_usecs(a,b)		(((b)-(a))*1000000LL)
#define time64_diff_nsecs(a,b)		(((b)-(a))*1000000000LL)


//-----------------------------------------------------------------------------
// typedef	timems_t
//
// purpose	Number of milliseconds since host epoch, in at least 64 bits,
//		with negative values representing time before the epoch.
//
// note		UNIX uses an epoch of 1970-01-01.00:00:00
//		There is currently no support for other host epochs.
//-----------------------------------------------------------------------------
typedef int64_t				timems_t	;

#define TIMEMS_C(c)			(INT64_C(c))
#define TIMEMS_ERROR			(INT64_MIN)
#define TIMEMS_MIN			(INT64_MIN+TIMEMS_C(1))
#define	TIMEMS_MAX			(INT64_MAX)

//-----------------------------------------------------------------------------
// Define macros to extract time parts from type timems_t.
//-----------------------------------------------------------------------------
#define timems_get_hour_of_day(t)	(mod_ni((t),TIMEMS_C(86400000))/TIMEMS_C(3600000))
#define timems_get_min_of_day(t)	(mod_ni((t),TIMEMS_C(86400000))/TIMEMS_C(60000))
#define timems_get_sec_of_day(t)	(mod_ni((t),TIMEMS_C(86400000))/TIMEMS_C(1000))
#define timems_get_msec_of_day(t)	(mod_ni((t),TIMEMS_C(86400000)))
#define timems_get_usec_of_day(t)	(mod_ni((t),TIMEMS_C(86400000))*TIMEMS_C(1000))
#define timems_get_nsec_of_day(t)	(mod_ni((t),TIMEMS_C(86400000))*TIMEMS_C(1000000))

#define timems_get_min_of_hour(t)	(mod_ni((t),TIMEMS_C(3600000))/TIMEMS_C(60000))
#define timems_get_sec_of_hour(t)	(mod_ni((t),TIMEMS_C(3600000))/TIMEMS_C(1000))
#define timems_get_msec_of_hour(t)	(mod_ni((t),TIMEMS_C(3600000)))
#define timems_get_usec_of_hour(t)	(mod_ni((t),TIMEMS_C(3600000))*TIMEMS_C(1000))
#define timems_get_nsec_of_hour(t)	(mod_ni((t),TIMEMS_C(3600000))*TIMEMS_C(1000000))

#define timems_get_sec_of_min(t)	(mod_ni((t),TIMEMS_C(60000))/TIMEMS_C(1000))
#define timems_get_msec_of_min(t)	(mod_ni((t),TIMEMS_C(60000)))
#define timems_get_usec_of_min(t)	(mod_ni((t),TIMEMS_C(60000))*TIMEMS_C(1000))
#define timems_get_nsec_of_min(t)	(mod_ni((t),TIMEMS_C(60000))*TIMEMS_C(1000000))

#define timems_get_msec_of_sec(t)	(mod_ni((t),TIMEMS_C(1000)))
#define timems_get_usec_of_sec(t)	(mod_ni((t),TIMEMS_C(1000))*TIMEMS_C(1000))
#define timems_get_nsec_of_sec(t)	(mod_ni((t),TIMEMS_C(1000))*TIMEMS_C(1000000))

#define timems_get_usec_of_msec(t)	(0)
#define timems_get_nsec_of_msec(t)	(0)

#define timems_get_nsec_of_usec(t)	(0)

//-----------------------------------------------------------------------------
// Define macros to add/subtract intervals of time to/from type timems_t.
//-----------------------------------------------------------------------------
#define timems_add_days(t,d)		((t)+(long long)(d)*86400000LL)
#define timems_add_hours(t,h)		((t)+(long long)(h)*3600000LL)
#define timems_add_mins(t,m)		((t)+(long long)(m)*60000LL)
#define timems_add_secs(t,s)		((t)+(long long)(s)*1000LL)
#define timems_add_msecs(t,m)		((t)+(long long)(m))
#define timems_add_usecs(t,u)		((t)+(long long)(u)/1000LL)
#define timems_add_nsecs(t,n)		((t)+(long long)(n)/1000000LL)

#define timems_sub_days(t,d)		((t)-(long long)(d)*86400000LL)
#define timems_sub_hours(t,h)		((t)-(long long)(h)*3600000LL)
#define timems_sub_mins(t,m)		((t)-(long long)(m)*60000LL)
#define timems_sub_secs(t,s)		((t)-(long long)(s)*1000LL)
#define timems_sub_msecs(t,m)		((t)-(long long)(m))
#define timems_sub_usecs(t,u)		((t)-(long long)(u)/1000LL)
#define timems_sub_nsecs(t,n)		((t)-(long long)(n)/1000000LL)

//-----------------------------------------------------------------------------
// Define macros to get the difference between two timems_t values and return
// the result in a specific relative scale.
//-----------------------------------------------------------------------------
#define timems_diff_days(a,b)		(quo_ni((b),86400000LL)-quo_ni((a),86400000LL))
#define timems_diff_hours(a,b)		(quo_ni((b),3600000LL)-quo_ni((a),3600000LL))
#define timems_diff_mins(a,b)		(quo_ni((b),60000LL)-quo_ni((a),60000LL))
#define timems_diff_secs(a,b)		(quo_ni((b),1000LL)-quo_ni((a),1000LL))
#define timems_diff_msecs(a,b)		((b)-(a))
#define timems_diff_usecs(a,b)		(((b)-(a))*1000LL)
#define timems_diff_nsecs(a,b)		(((b)-(a))*1000000LL)


//-----------------------------------------------------------------------------
// typedef	timeus_t
//
// purpose	Number of microseconds since host epoch, in at least 64 bits,
//		with negative values representing time before the epoch.
//
// note		UNIX uses an epoch of 1970-01-01.00:00:00
//		There is currently no support for other host epochs.
//-----------------------------------------------------------------------------
typedef int64_t				timeus_t	;

#define TIMEUS_C(c)			(INT64_C(c))
#define TIMEUS_MIN			(INT64_MIN+TIMEUS_C(1))
#define	TIMEUS_MAX			(INT64_MAX)

//-----------------------------------------------------------------------------
// Define macros to extract time parts from type timeus_t.
//-----------------------------------------------------------------------------
#define timeus_get_hour_of_day(t)	(mod_ni((t),TIMEUS_C(86400000000))/TIMEUS_C(3600000000))
#define timeus_get_min_of_day(t)	(mod_ni((t),TIMEUS_C(86400000000))/TIMEUS_C(60000000))
#define timeus_get_sec_of_day(t)	(mod_ni((t),TIMEUS_C(86400000000))/TIMEUS_C(1000000))
#define timeus_get_msec_of_day(t)	(mod_ni((t),TIMEUS_C(86400000000))/TIMEUS_C(1000))
#define timeus_get_usec_of_day(t)	(mod_ni((t),TIMEUS_C(86400000000)))
#define timeus_get_nsec_of_day(t)	(mod_ni((t),TIMEUS_C(86400000000))*TIMEUS_C(1000))

#define timeus_get_min_of_hour(t)	(mod_ni((t),TIMEUS_C(3600000000))/TIMEUS_C(60000000))
#define timeus_get_sec_of_hour(t)	(mod_ni((t),TIMEUS_C(3600000000))/TIMEUS_C(1000000))
#define timeus_get_msec_of_hour(t)	(mod_ni((t),TIMEUS_C(3600000000))/TIMEUS_C(1000))
#define timeus_get_usec_of_hour(t)	(mod_ni((t),TIMEUS_C(3600000000)))
#define timeus_get_nsec_of_hour(t)	(mod_ni((t),TIMEUS_C(3600000000))*TIMEUS_C(1000))

#define timeus_get_sec_of_min(t)	(mod_ni((t),TIMEUS_C(60000000))/TIMEUS_C(1000000))
#define timeus_get_msec_of_min(t)	(mod_ni((t),TIMEUS_C(60000000))/TIMEUS_C(1000))
#define timeus_get_usec_of_min(t)	(mod_ni((t),TIMEUS_C(60000000)))
#define timeus_get_nsec_of_min(t)	(mod_ni((t),TIMEUS_C(60000000))*TIMEUS_C(1000))

#define timeus_get_msec_of_sec(t)	(mod_ni((t),TIMEUS_C(1000000))/TIMEUS_C(1000))
#define timeus_get_usec_of_sec(t)	(mod_ni((t),TIMEUS_C(1000000)))
#define timeus_get_nsec_of_sec(t)	(mod_ni((t),TIMEUS_C(1000000))*TIMEUS_C(1000))

#define timeus_get_usec_of_msec(t)	(mod_ni((t),TIMEUS_C(1000)))
#define timeus_get_nsec_of_msec(t)	(mod_ni((t),TIMEUS_C(1000))*TIMEUS_C(1000))

#define timeus_get_nsec_of_usec(t)	(0)

//-----------------------------------------------------------------------------
// Define macros to add/subtract intervals of time to/from type timeus_t.
//-----------------------------------------------------------------------------
#define timeus_add_days(t,d)		((t)+(long long)(d)*86400000000LL)
#define timeus_add_hours(t,h)		((t)+(long long)(h)*3600000000LL)
#define timeus_add_mins(t,m)		((t)+(long long)(m)*60000000LL)
#define timeus_add_secs(t,s)		((t)+(long long)(s)*1000000LL)
#define timeus_add_msecs(t,m)		((t)+(long long)(m)*1000LL)
#define timeus_add_usecs(t,u)		((t)+(long long)(u))
#define timeus_add_nsecs(t,n)		((t)+(long long)(n)/1000LL)

#define timeus_sub_days(t,d)		((t)-(long long)(d)*86400000000LL)
#define timeus_sub_hours(t,h)		((t)-(long long)(h)*3600000000LL)
#define timeus_sub_mins(t,m)		((t)-(long long)(m)*60000000LL)
#define timeus_sub_secs(t,s)		((t)-(long long)(s)*1000000LL)
#define timeus_sub_msecs(t,m)		((t)-(long long)(m)*1000LL)
#define timeus_sub_usecs(t,u)		((t)-(long long)(u))
#define timeus_sub_nsecs(t,n)		((t)-(long long)(n)/1000LL)

//-----------------------------------------------------------------------------
// Define macros to get the difference between two timeus_t values and return
// the result in a specific relative scale.
//-----------------------------------------------------------------------------
#define timeus_diff_days(a,b)		(quo_ni((b),86400000000LL)-quo_ni((a),86400000000LL))
#define timeus_diff_hours(a,b)		(quo_ni((b),3600000000LL)-quo_ni((a),3600000000LL))
#define timeus_diff_mins(a,b)		(quo_ni((b),60000000LL)-quo_ni((a),60000000LL))
#define timeus_diff_secs(a,b)		(quo_ni((b),1000000LL)-quo_ni((a),1000000LL))
#define timeus_diff_msecs(a,b)		(quo_ni((b),1000LL)-quo_ni((a),1000LL))
#define timeus_diff_usecs(a,b)		((b)-(a))
#define timeus_diff_nsecs(a,b)		(((b)-(a))*1000LL)


//-----------------------------------------------------------------------------
// typedef	timens_t
//
// purpose	Number of nanoseconds since host epoch, in at least 64 bits,
//		with negative values representing time before the epoch.
//
// note		UNIX uses an epoch of 1970-01-01.00:00:00
//		There is currently no support for other host epochs.
//-----------------------------------------------------------------------------
typedef int64_t				timens_t	;

#define TIMENS_C(c)			(INT64_C(c))
#define TIMENS_ERROR			(INT64_MIN)
#define TIMENS_MIN			(INT64_MIN+TIMENS_C(1))
#define	TIMENS_MAX			(INT64_MAX)

//-----------------------------------------------------------------------------
// Define macros to extract time parts from type timens_t.
//-----------------------------------------------------------------------------
#define timens_get_hour_of_day(t)	(mod_ni((t),TIMENS_C(86400000000000))/TIMENS_C(3600000000000))
#define timens_get_min_of_day(t)	(mod_ni((t),TIMENS_C(86400000000000))/TIMENS_C(60000000000))
#define timens_get_sec_of_day(t)	(mod_ni((t),TIMENS_C(86400000000000))/TIMENS_C(1000000000))
#define timens_get_msec_of_day(t)	(mod_ni((t),TIMENS_C(86400000000000))/TIMENS_C(1000000))
#define timens_get_usec_of_day(t)	(mod_ni((t),TIMENS_C(86400000000000))/TIMENS_C(1000))
#define timens_get_nsec_of_day(t)	(mod_ni((t),TIMENS_C(86400000000000)))

#define timens_get_min_of_hour(t)	(mod_ni((t),TIMENS_C(3600000000000))/TIMENS_C(60000000000))
#define timens_get_sec_of_hour(t)	(mod_ni((t),TIMENS_C(3600000000000))/TIMENS_C(1000000000))
#define timens_get_msec_of_hour(t)	(mod_ni((t),TIMENS_C(3600000000000))/TIMENS_C(1000000))
#define timens_get_usec_of_hour(t)	(mod_ni((t),TIMENS_C(3600000000000))/TIMENS_C(1000))
#define timens_get_nsec_of_hour(t)	(mod_ni((t),TIMENS_C(3600000000000)))

#define timens_get_sec_of_min(t)	(mod_ni((t),TIMENS_C(60000000000))/TIMENS_C(1000000000))
#define timens_get_msec_of_min(t)	(mod_ni((t),TIMENS_C(60000000000))/TIMENS_C(1000000))
#define timens_get_usec_of_min(t)	(mod_ni((t),TIMENS_C(60000000000))/TIMENS_C(1000))
#define timens_get_nsec_of_min(t)	(mod_ni((t),TIMENS_C(60000000000)))

#define timens_get_msec_of_sec(t)	(mod_ni((t),TIMENS_C(1000000000))/TIMENS_C(1000000))
#define timens_get_usec_of_sec(t)	(mod_ni((t),TIMENS_C(1000000000))/TIMENS_C(1000))
#define timens_get_nsec_of_sec(t)	(mod_ni((t),TIMENS_C(1000000000)))

#define timens_get_usec_of_msec(t)	(mod_ni((t),TIMENS_C(1000000))/TIMENS_C(1000))
#define timens_get_nsec_of_msec(t)	(mod_ni((t),TIMENS_C(1000000)))

#define timens_get_nsec_of_usec(t)	(mod_ni((t),TIMENS_C(1000)))

//-----------------------------------------------------------------------------
// Define macros to add/subtract intervals of time to/from type timens_t.
//-----------------------------------------------------------------------------
#define timens_add_days(t,d)		((t)+(long long)(d)*86400000000000LL)
#define timens_add_hours(t,h)		((t)+(long long)(h)*3600000000000LL)
#define timens_add_mins(t,m)		((t)+(long long)(m)*60000000000LL)
#define timens_add_secs(t,s)		((t)+(long long)(s)*1000000000LL)
#define timens_add_msecs(t,m)		((t)+(long long)(m)*1000000LL)
#define timens_add_usecs(t,u)		((t)+(long long)(u)*1000LL)
#define timens_add_nsecs(t,n)		((t)+(long long)(n))

#define timens_sub_days(t,d)		((t)-(long long)(d)*86400000000000LL)
#define timens_sub_hours(t,h)		((t)-(long long)(h)*3600000000000LL)
#define timens_sub_mins(t,m)		((t)-(long long)(m)*60000000000LL)
#define timens_sub_secs(t,s)		((t)-(long long)(s)*1000000000LL)
#define timens_sub_msecs(t,m)		((t)-(long long)(m)*1000000LL)
#define timens_sub_usecs(t,u)		((t)-(long long)(u)*1000LL)
#define timens_sub_nsecs(t,n)		((t)-(long long)(n))

//-----------------------------------------------------------------------------
// Define macros to get the difference between two timens_t values and return
// the result in a specific relative scale.
//-----------------------------------------------------------------------------
#define timens_diff_days(a,b)		(quo_ni((b),86400000000000LL)-quo_ni((a),86400000000000LL))
#define timens_diff_hours(a,b)		(quo_ni((b),3600000000000LL)-quo_ni((a),3600000000000LL))
#define timens_diff_mins(a,b)		(quo_ni((b),60000000000LL)-quo_ni((a),60000000000LL))
#define timens_diff_secs(a,b)		(quo_ni((b),1000000000LL)-quo_ni((a),1000000000LL))
#define timens_diff_msecs(a,b)		(quo_ni((b),1000000LL)-quo_ni((a),1000000LL))
#define timens_diff_usecs(a,b)		(quo_ni((b),1000LL)-quo_ni((a),1000LL)))
#define timens_diff_nsecs(a,b)		((b)-(a))



//-----------------------------------------------------------------------------
// Define macros to convert absolute time from one scale/epoch to another.
//-----------------------------------------------------------------------------
#define etime_to_eday(t)		((eday_t)quo_ni((t),ETIME_C(86400000000)))
#define etime_to_lday(t)		(eday_to_lday((etime_to_eday(t))))
#define etime_to_xday(t)		(eday_to_xday((etime_to_eday(t))))
#define etime_to_time(t)		((time_t)quo_ni(((etime_t)(t)-ETIME_UNIX_EPOCH),1000000U))
#define etime_to_timems(t)		((timems_t)quo_ni(((etime_t)(t)-ETIME_UNIX_EPOCH),1000U))
#define etime_to_timeus(t)		((timeus_t)((time_t)(((etime_t)(t)-ETIME_UNIX_EPOCH))))
#define etime_to_timens(t)		((timens_t)(((etime_t)(t)-ETIME_UNIX_EPOCH)*1000U))

#define eday_to_etime(t)		(((etime_t)(t))*ETIME_C(86400000000))
#define eday_to_lday(t)			((lday_t)(t)-EDAY_14_OCT_1582)
#define eday_to_xday(t)			((xday_t)(t)-2000000)
#define eday_to_time(t)			(((time_t)((eday_t)(t)-EDAY_UNIX_EPOCH))*86400)
#define eday_to_time64(t)		(((time64_t)((eday_t)(t)-EDAY_UNIX_EPOCH))*TIME64_C(86400))
#define eday_to_timems(t)		(((int64_t)((eday_t)(t)-EDAY_UNIX_EPOCH))*TIMEMC_C(86400000))
#define eday_to_timeus(t)		(((int64_t)((eday_t)(t)-EDAY_UNIX_EPOCH))*TIMEUS_C(86400000000))
#define eday_to_timens(t)		(((int64_t)((eday_t)(t)-EDAY_UNIX_EPOCH))*TIMENS_C(86400000000000))

#define lday_to_etime(t)		(eday_to_etime((lday_to_eday(t))))
#define lday_to_eday(t)			((eday_t)(t)+EDAY_14_OCT_1582)
#define lday_to_xday(t)			((xday_t)(t)+XDAY_14_OCT_1582)
#define lday_to_time(t)			(((time_t)((lday_t)(t)-LDAY_UNIX_EPOCH))*86400)
#define lday_to_time64(t)		(((time64_t)((lday_t)(t)-LDAY_UNIX_EPOCH))*TIME64_C(86400))
#define lday_to_timems(t)		(((int64_t)((lday_t)(t)-LDAY_UNIX_EPOCH))*TIMEMS_C(86400000))
#define lday_to_timeus(t)		(((int64_t)((lday_t)(t)-LDAY_UNIX_EPOCH))*TIMEUS_C(86400000000))
#define lday_to_timens(t)		(((int64_t)((lday_t)(t)-LDAY_UNIX_EPOCH))*TIMENS_C(86400000000000))

#define xday_to_etime(t)		(eday_to_etime((xday_to_eday(t))))
#define xday_to_eday(t)			((eday_t)(t)+2000000)
#define xday_to_lday(t)			((lday_t)(t)-XDAY_14_OCT_1582)
#define xday_to_time(t)			(((time_t)((xday_t)(t)-XDAY_UNIX_EPOCH))*86400)
#define xday_to_time64(t)		(((time64_t)((xday_t)(t)-XDAY_UNIX_EPOCH))*TIME64_C(86400))
#define xday_to_timems(t)		(((int64_t)((xday_t)(t)-XDAY_UNIX_EPOCH))*TIMEMS_C(86400000))
#define xday_to_timeus(t)		(((int64_t)((xday_t)(t)-XDAY_UNIX_EPOCH))*TIMEUS_C(86400000000))
#define xday_to_timens(t)		(((int64_t)((xday_t)(t)-XDAY_UNIX_EPOCH))*TIMENS_C(86400000000000))

#define time_to_etime(t)		((((etime_t)(t))*ETIME_C(1000000))+ETIME_UNIX_EPOCH)
#define time_to_eday(t)			((eday_t)(quo_ni((t),86400U)+EDAY_UNIX_EPOCH))
#define time_to_lday(t)			((lday_t)(quo_ni((t),86400U)+LDAY_UNIX_EPOCH))
#define time_to_xday(t)			((xday_t)(quo_ni((t),86400U)+XDAY_UNIX_EPOCH))
#define time_to_timems(t)		(((timems_t)(t))*TIMEMS_C(1000))
#define time_to_timeus(t)		(((timeus_t)(t))*TIMEUS_C(1000000))
#define time_to_timens(t)		(((timens_t)(t))*TIMENS_C(1000000000))

#define time64_to_etime(t)		((((etime_t)(t))*ETIME_C(1000000))+ETIME_UNIX_EPOCH)
#define time64_to_eday(t)		((eday_t)(quo_ni((t),TIME64_C(86400))+EDAY_UNIX_EPOCH))
#define time64_to_lday(t)		((lday_t)(quo_ni((t),TIME64_C(86400))+LDAY_UNIX_EPOCH))
#define time64_to_xday(t)		((xday_t)(quo_ni((t),TIME64_C(86400))+XDAY_UNIX_EPOCH))
#define time64_to_timems(t)		(((timeus_t)(t))*TIMEMS_C(1000))
#define time64_to_timeus(t)		(((timens_t)(t))*TIMEUS_C(1000000))
#define time64_to_timens(t)		(((timeus_t)(t))*TIMENS_C(1000000000))

#define timems_to_etime(t)		((((etime_t)(t))*ETIME_C(1000))+ETIME_UNIX_EPOCH)
#define timems_to_eday(t)		((eday_t)(quo_ni((t),TIMEMS_C(86400000))+EDAY_UNIX_EPOCH))
#define timems_to_lday(t)		((lday_t)(quo_ni((t),TIMEMS_C(86400000))+LDAY_UNIX_EPOCH))
#define timems_to_xday(t)		((xday_t)(quo_ni((t),TIMEMS_C(86400000))+XDAY_UNIX_EPOCH))
#define timems_to_time(t)		((time_t)quo_ni((t),TIMEMS_C(1000)))
#define timems_to_timeus(t)		(((timeus_t)(t))*TIMEUS_C(1000))
#define timems_to_timens(t)		(((timens_t)(t))*TIMENS_C(1000000))

#define timeus_to_etime(t)		(((etime_t)(t))+ETIME_UNIX_EPOCH)
#define timeus_to_eday(t)		((eday_t)(quo_ni((t),TIMEUS_C(86400000000))+EDAY_UNIX_EPOCH))
#define timeus_to_lday(t)		((lday_t)(quo_ni((t),TIMEUS_C(86400000000))+LDAY_UNIX_EPOCH))
#define timeus_to_xday(t)		((xday_t)(quo_ni((t),TIMEUS_C(86400000000))+XDAY_UNIX_EPOCH))
#define timeus_to_time(t)		((time_t)quo_ni((t),TIMEUS_C(1000000)))
#define timeus_to_timems(t)		((timems_t)quo_ni((t),TIMEUS_C(1000)))
#define timeus_to_timens(t)		(((timens_t)(t))*TIMENS_C(1000))

#define timens_to_etime(t)		(((etime_t)quo_ni((t),ETIME_C(1000)))+ETIME_UNIX_EPOCH)
#define timens_to_eday(t)		((eday_t)(quo_ni((t),TIMENS_C(86400000000000))+EDAY_UNIX_EPOCH))
#define timens_to_lday(t)		((lday_t)(quo_ni((t),TIMENS_C(86400000000000))+LDAY_UNIX_EPOCH))
#define timens_to_xday(t)		((xday_t)(quo_ni((t),TIMENS_C(86400000000000))+XDAY_UNIX_EPOCH))
#define timens_to_time(t)		((time_t)quo_ni((t),TIMENS_C(1000000000)))
#define timens_to_timems(t)		((timems_t)quo_ni((t),TIMENS_C(1000000)))
#define timens_to_timeus(t)		((timeus_t)quo_ni((t),TIMENS_C(1000)))

#define etime_to_dsec(t)		mod_ni(quo_ni((t),ETIME_C(1000000)),ETIME_C(86400))
#define etime_to_dmsec(t)		mod_ni(quo_ni((t),ETIME_C(1000)),TIMEMS_C(86400000))
#define etime_to_dusec(t)		mod_ni((t),TIMEUS_C(86400000000))
#define etime_to_dnsec(t)		mod_ni((t)*ETIME_C(1000),TIMENS_C(86400000000000))

#define ecal_to_time(c)			(etime_to_time(ecal_to_etime((c))))
#define ymd_gregorian_to_time(y,m,d)		(etime_to_time(ymd_gregorian_to_etime((y),(m),(d))))
#define ymd_julian_to_time(y,m,d)		(etime_to_time(ymd_julian_to_etime((y),(m),(d))))


//-----------------------------------------------------------------------------
// other macros
//-----------------------------------------------------------------------------
#define time_to_str_app(d,s,f,t)	etime_to_str_app((d),(s),(f),time_to_etime((t)))
#define time_to_str_cpy(d,s,f,t)	etime_to_str_app((d),(s),(f),time_to_etime((t)))
#define time_to_str_dup(f,t)		etime_to_str_app((f),time_to_etime((t)))

#define time_to_eprintf(f,t)		etime_to_eprintf((f),time_to_etime((t)))
#define time_to_fprintf(o,f,t)		etime_to_fprintf((o),(f),time_to_etime((t)))
#define time_to_printf(f,t)		etime_to_printf((f),time_to_etime((t)))

#define timems_to_eprintf(f,t)		etime_to_eprintf((f),timems_to_etime((t)))
#define timems_to_fprintf(o,f,t)	etime_to_fprintf((o),(f),timems_to_etime((t)))
#define timems_to_printf(f,t)		etime_to_printf((f),timems_to_etime((t)))

#define timeus_to_eprintf(f,t)		etime_to_eprintf((f),timeus_to_etime((t)))
#define timeus_to_fprintf(o,f,t)	etime_to_fprintf((o),(f),timeus_to_etime((t)))
#define timeus_to_printf(f,t)		etime_to_printf((f),timeus_to_etime((t)))

#define timens_to_eprintf(f,t)		etime_to_eprintf((f),timens_to_etime((t)))
#define timens_to_fprintf(o,f,t)	etime_to_fprintf((o),(f),timens_to_etime((t)))
#define timens_to_printf(f,t)		etime_to_printf((f),timens_to_etime((t)))

__DEFINE_END__

__SUFFIX_BEGIN__
#endif /* __TIME_H__ */
__SUFFIX_END__

