//	ggdt.c		gg630504 hg9ieg linux.ubuntu.gcc
//	2012-11-07

#include <time.h>

#include "ggstd.h"
#include "ggdt.h"

DMD dmdLenDylDym[ dylLim ][ dymLim ] = {
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };

DWD dwdBegin = dwdSun;

DYD dydOffsDylDym[ dylLim ][ dymLim ] = {
{ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } };

TDH tdhMapTdh[ tdh24Lim ] = { 
12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };

TDP tdpMapTdh[ tdh24Lim ] = { 
tdpAm, tdpAm, tdpAm, tdpAm, tdpAm, tdpAm, tdpAm, tdpAm, tdpAm, tdpAm, tdpAm, tdpAm, 
tdpPm, tdpPm, tdpPm, tdpPm, tdpPm, tdpPm, tdpPm, tdpPm, tdpPm, tdpPm, tdpPm, tdpPm };

// dátum szövegek magyar, angol
static CH szInvalid[] = "?";

SZ szMaplLanDwd[ lanLim ][ dwdLim ] = {
{ "vasárnap", "hétfő", "kedd", "szerda", "csütörtök", "péntek", "szombat" },
{ "sunday", "monday", "tuesday", "wednesday", "thrusday", "friday", "saturday" } };

SZ szMaplLanDym[ lanLim ][ dymLim ] = {
{ szInvalid, "január", "február", "március", "április", "május", "június", "július", "augusztus", "szeptember", "október", "november", "december" },
{ szInvalid, "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december" } };

SZ szMapsLanDwd[ lanLim ][ dwdLim ] = {
{ "vas", "hét", "ked", "sze", "csü", "pén", "szo" },
{ "sun", "mon", "tue", "wed", "thu", "fri", "sat" } };

SZ szMapsLanDym[ lanLim ][ dymLim ] = {
{ szInvalid, "jan", "feb", "már", "ápr", "máj", "jún", "júl", "aug", "sze", "okt", "nov", "dec" },
{ szInvalid, "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" } };

SZ szMapLanTpd[ lanLim ][ tdpLim ] = {
{ "de.", "du." },
{ "am", "pm" } };


//$  DywFromLanDdDd ----------------------------------------------------
// hét részszámítás
DYW		DywFromLanDdDd( lan_, dd0_, dd1_ )
LAN		lan_; //
DD		dd0_; // jan. 1.
DD		dd1_; // a nap
{
switch( lan_ )
	{
case	lanHun:
	return( (DYW)( (dd1_ - dd0_ + (DD)DwdFromDd( dd0_ )-1)/7L ) );
default:
	return( (DYW)( (dd1_ - dd0_ + (DD)DwdFromDd( dd0_ ))/7L+1L ) );
	}
}


//$ DdFromPdt ----------------------------------------------------------
// dátum számolása dátum és időből
DD		DdFromPdt( pdt_ )
PDT		pdt_;
{
return( DdFromPdtd( &pdt_->dtd ) );
}


//$ DdFromPdtd ---------------------------------------------------------
// nap számolása dátumból
DD		DdFromPdtd( pdtd_ )
PDTD		pdtd_;
{
DY		dy;

dy = pdtd_->dy-1;
return( +(DD)( (pdtd_->dy)*365L )
	+(DD)(	+( dy / 4 )
		-( dy / 100 )
		+( dy / 400 )
		+( pdtd_->dy>0 )
		+( dydOffsDylDym[ DylFromDy(pdtd_->dy) ][ pdtd_->dym ] )
		+( pdtd_->dmd )
		-1 ) );
}



//$ DjFromPdt ----------------------------------------------------------
// Julián dátum számolása dátumidőből
DJ		DjFromPdt( pdt_ )
PDT		pdt_;
{
return( ( DdFromPdtd( &pdt_->dtd )+1721059L ) + ( (DsFromPdtt( &pdt_->dtt )+43200l) / 86400.0 ) );
}


//$ DmjFromPdt ---------------------------------------------------------
DMJ		DmjFromPdt( pdt_ )
PDT		pdt_;
{
return( ( DdFromPdtd( &pdt_->dtd )-678941L ) + ( DsFromPdtt( &pdt_->dtt ) / 86400.0 ) );
}


//$ DsFromPdt ----------------------------------------------------------
// másodperc számolása dátumidőből
DS		DsFromPdt( pdt0_ )
PDT		pdt0_;
{
return( DsFromPdtt(&pdt0_->dtt)+86400L*(DdFromPdtd(&pdt0_->dtd) ) );
}


//$ DsFromPdtt ---------------------------------------------------------
// másodperc számolása időből
DS		DsFromPdtt( pdtt_ )
PDTT		pdtt_;
{
return( (DS)( 3600L*pdtt_->tdh ) + (DS)( 60L*pdtt_->thm + pdtt_->tms ) );
}


//$ DsSubPdtPdt -------------------------------------------------------
// két dátum különbsége másodpercben
DS		DsSubPdtPdt( pdt0_, pdt1_ )
PDT		pdt0_;
PDT		pdt1_;
{
return( DsFromPdtt(&pdt0_->dtt) - DsFromPdtt(&pdt1_->dtt)+ 86400L*(DdFromPdtd(&pdt0_->dtd)-DdFromPdtd(&pdt1_->dtd) ) );
}


//$ DwdFromDd ----------------------------------------------------------
// hét napjának számolása napból
DWD		DwdFromDd( dy_ )
DD		dy_;
{
return( (DWD)( (dy_+6L) % 7 ) );
}


//$ DwdFromPdt ---------------------------------------------------------
// hét napjának számolása dátumidőből
DWD		DwdFromPdt( pdt_ )
PDT		pdt_;
{
return( DwdFromPdtd( &pdt_->dtd ) );
}


//$ DwdFromPdtd --------------------------------------------------------
// hét napjának számolása dátumból
DWD		DwdFromPdtd( dp_ )
PDTD		dp_;
{
return( DwdFromDd( DdFromPdtd( dp_ ) ) );
}


//$ DydFromLanPdt ------------------------------------------------------
// év napjának számolása dátumidőből
DYD		DydFromLanPdt( pdt_ )
PDT		pdt_;
{
return( DydFromPdtd( &(pdt_->dtd) ) );
}


//$ DydFromPdt ---------------------------------------------------------
// év napjának számolása dátumból
DYD		DydFromPdtd( pdtd_ )
PDTD		pdtd_;
{
DTD		dtd;

dtd.dy = pdtd_->dy;
dtd.dym = dymFirst;
dtd.dmd = dmdFirst;
return( (DYD)(DdFromPdtd( pdtd_ ) - DdFromPdtd( &dtd )) );
}


//$ DylFromDy ----------------------------------------------------------
// szökőév számolása évből
DYL		DylFromDy( dy_ )
DY		dy_;
{
if( ( dy_ % 4 ) == 0 )
	if( ( dy_ % 100 ) == 0 )
		if( ( dy_ % 400 ) == 0 )
			return( dylYes );
		else	return( dylNo );
	else	return( dylYes );
else	return( dylNo );
}


//$ DywFromLanDd -------------------------------------------------------
// év hetének számolása napból
DYW		DywFromLanDd( lan_, dd_ )
LAN		lan_;
DD		dd_;

{
DTD		dtd; // ev jan 1.

PdtdFromPdtdDd( &dtd, dd_ );
dtd.dym = dymFirst;
dtd.dmd = dmdFirst;
return( DywFromLanDdDd( lan_, DdFromPdtd( &dtd ), dd_ ) );
}


//$ DywFromLanPdt ------------------------------------------------------
// év hetének számolása dátumidőből
DYW		DywFromLanPdt( lan_, pdt_ )
LAN		lan_;
PDT		pdt_;
{
return( DywFromLanPdtd( lan_, &pdt_->dtd ) );
}


//$ DywFromLanPdtd -----------------------------------------------------
// év hetének számolása dátumból
DYW		DywFromLanPdtd( lan_, pdtd_ )
LAN		lan_;
PDTD		pdtd_;
{
DTD		dtd; // év jan 1

dtd.dy = pdtd_->dy;
dtd.dym = dymFirst;
dtd.dmd = dmdFirst;
return( DywFromLanDdDd( lan_, DdFromPdtd( &dtd ), DdFromPdtd( pdtd_ ) ) );
}


//$ FDayLightPdt -------------------------------------------------------
// nyári időszámítás
F		FDayLightPdt( pdt_ )
PDT		pdt_;
{
DWD		dwd;
W		wTmp;

if( pdt_->dtd.dym<dymMar || pdt_->dtd.dym>dymOct )
	return( fFalse );

if( pdt_->dtd.dym>dymMar && pdt_->dtd.dym<dymOct )
	return( fTrue );

if( pdt_->dtd.dym==dymMar )
	{
	if( pdt_->dtd.dmd<25 )
		return( fFalse );
	dwd = DwdFromPdt( pdt_ );
	wTmp = (W)pdt_->dtd.dmd-(W)dwd;
	if( wTmp<25 )
		return( fFalse );
	if( dwd!=dwdSun )
		return( fTrue );
	if( pdt_->dtt.tdh>=1 )
		return( fTrue );
	else	return( fFalse );
	}
else	{ // okt
	if( pdt_->dtd.dmd<25 )
		return( fTrue );
	dwd = DwdFromPdt( pdt_ );
	wTmp = (W)pdt_->dtd.dmd-(W)dwd;
	if( wTmp>=25 )
		{
		if( dwd!=dwdSun )
			return( fFalse );
		if( pdt_->dtt.tdh>=1 )
			return( fFalse );
		else	return( fTrue );
		}
	else	return( fTrue );
	}
}


//$ FNoWorkPdtd --------------------------------------------------------
// munkaszüneti nap dátumból
F		FNoWorkPdtd( pdtd_ )
PDTD		pdtd_;
{
DWD		dwd;

dwd = DwdFromPdtd( pdtd_ );

if( dwd==dwdSat || dwd==dwdSun )		return( fTrue );
if( pdtd_->dym==dymJan && pdtd_->dmd== 1 )	return( fTrue );
if( pdtd_->dym==dymMar && pdtd_->dmd==15 )	return( fTrue );
if( pdtd_->dym==dymAug && pdtd_->dmd==20 )	return( fTrue );
if( pdtd_->dym==dymOct && pdtd_->dmd==23 )	return( fTrue );
if( pdtd_->dym==dymDec && pdtd_->dmd==25 )	return( fTrue );
if( pdtd_->dym==dymDec && pdtd_->dmd==26 )	return( fTrue );
return( fFalse );
}


//$ PdtAddPdtD ---------------------------------------------------------
// dátumidőhöz másodperc adása
PDT		PdtAddPdtDs( pdt_, ds_ )
PDT		pdt_;
DS		ds_;
{
W		ds;
W		dd;

ds = DsFromPdtt( &pdt_->dtt ) + ds_;

if( ds<0 )
	{
	ds = -ds;
	dd = -(ds / 86400L)-1;
	ds = 86400L-(ds % 86400L);
	}
else	{
	dd = ds / 86400L;
	ds = ds % 86400L;
	}

if( dd!=0L )
	PdtdAddDPdtdW( &pdt_->dtd, dd );

PdttFromPdttDs( &pdt_->dtt, ds );

return( pdt_ );
}


//$ PdtdAddDPdtdW ------------------------------------------------------
// dátumhoz nap adása
PDTD		PdtdAddDPdtdW( pdtd_, l_ )
PDTD		pdtd_;
W		l_;
{
return( PdtdFromPdtdDd( pdtd_, DdFromPdtd( pdtd_ )+l_ ) );
}


//$ PdtdAddMPdtdW ------------------------------------------------------
// dátumhoz hónap adása
PDTD		PdtdAddMPdtdW( pdtd_, l_ )
PDTD		pdtd_;
W		l_;
{
DM		dm;
DMD		dmd;

// átszámol hónapokba
dm = dymLim*pdtd_->dy + (pdtd_->dym-dymFirst) + l_;

// visszaszámol évbe, hónapba
pdtd_->dy = (DY)(dm / dymLim);
pdtd_->dym = (DYM)( dm % dymLim )+dymFirst;

// február 29-e csak néha van!
if( pdtd_->dmd>28 )
	{
	dmd = dmdLenDylDym[ DylFromDy( pdtd_->dy ) ][ dymFeb ];
	if( pdtd_->dmd > dmd )
		pdtd_->dmd = dmd;
	}
return( pdtd_ );
}


//$ PdtdAddYPdtdW ------------------------------------------------------
// dátumhoz év adása
PDTD		PdtdAddYPdtdW( pdtd_, l_ )
PDTD		pdtd_;
W		l_;
{
pdtd_->dy += l_;

// február 29-e csak néha van!
if( ( pdtd_->dym == dymFeb ) &&
	( pdtd_->dmd == 29 ) &&
	DylFromDy( pdtd_->dy ) == dylYes )
	pdtd_->dmd = 28;
return( pdtd_ );
}


//$ PdtdFromPdtdDd -----------------------------------------------------
// dátum számolása napból
PDTD		PdtdFromPdtdDd( pdtd_, dy_ )
PDTD		pdtd_;
DD		dy_;
{
DY		dy400;
DY		dy100;
DY		dy004;
DY		dy001;
DD		ddLeft;
DYL		dyl;

// 400 év...
dy400 = (DY)( dy_ / dd_400 );
ddLeft = dy_ - (DD)( dy400*dd_400 );

// 100 év...
VPdyPddDdDdDd( &dy100, &ddLeft, dd_100, dd_200, dd_300 );

if( dy100 == 0 )
	{
	dy004 = (DY)( ddLeft / dd_004 );
	ddLeft %= dd_004;
	VPdyPddDdDdDd( &dy001, &ddLeft, dd_001, dd_002, dd_003 );
	dyl = dy001==0;
	}
else	if( ddLeft<dd_004_1 )
		{
		dy004 = 0;
		dy001 = (DY)( ddLeft / 365L );
		ddLeft %= 365L;
		dyl = dylNo;
		}
	else	{
		ddLeft -= dd_004-1L;
		dy004 = (DY)( ddLeft / dd_004 )+1;
		ddLeft %= dd_004;
		VPdyPddDdDdDd( &dy001, &ddLeft, dd_001, dd_002, dd_003 );
		dyl = dy001==0;
		}

pdtd_->dy = 400*dy400+ 100*dy100+ 004*dy004+ dy001;

// hónap...
pdtd_->dym = dymLim-1;
while( (DD)(dydOffsDylDym[ dyl ][ pdtd_->dym ]) > ddLeft )
	--pdtd_->dym;

// nap...
pdtd_->dmd = ddLeft - dydOffsDylDym[ dyl ][ pdtd_->dym ]+1;

return( pdtd_ );
}


//$ PdtdOsUTCPdtd ------------------------------------------------------
// rendszeróra
PDTD		PdtdOsUTCPdtd( pdtd_ )
PDTD		pdtd_;
{
struct tm	tmUT;
time_t		tUT;

time( &tUT );
gmtime_r( &tUT, &tmUT );

pdtd_->dy  = tmUT.tm_year+1900;
pdtd_->dym = tmUT.tm_mon+1;
pdtd_->dmd = tmUT.tm_mday;

return( pdtd_ );
}


//$ PdtFromPdtDd -------------------------------------------------------
// dátum és idő számolása napból
PDT		PdtFromPdtDd( pdt_, dd_ )
PDT		pdt_;
DD		dd_;
{
PdtdFromPdtdDd( &pdt_->dtd, dd_ );
pdt_->dtt.tdh =
pdt_->dtt.thm =
pdt_->dtt.tms = 0;
// pdt_->dsZ = 0L;
return( pdt_ );
}


//$ PdtFromPdtDs -------------------------------------------------------
// idő számolása másodpercből
PDT		PdtFromPdtDs( pdt_, ds_ )
PDT		pdt_;
DS		ds_;
{
PdttFromPdttDs( &pdt_->dtt, ds_ );
return( pdt_ );
}


//$ PdtOsUTCPdt --------------------------------------------------------
// rendszeróra
PDT		PdtOsUTCPdt( pdt_ )
PDT		pdt_;
{
struct tm	tmUT;
time_t		tUT;

time( &tUT );
gmtime_r( &tUT, &tmUT );

pdt_->dtd.dy  = tmUT.tm_year+1900;
pdt_->dtd.dym = tmUT.tm_mon+1;
pdt_->dtd.dmd = tmUT.tm_mday;

pdt_->dtt.tdh = tmUT.tm_hour;
pdt_->dtt.thm = tmUT.tm_min;
pdt_->dtt.tms = tmUT.tm_sec;

return( pdt_ );
}


//$ PdttFromPdttDs -----------------------------------------------------
// idő számolása másodpercből
PDTT		PdttFromPdttDs( pdtt_, ds_ )
PDTT		pdtt_;
DS		ds_;
{
if( ds_>0 )
	{
	pdtt_->tms = (TMS)(ds_ % 60L);
	ds_ /= 60L;
	pdtt_->thm = (THM)(ds_ % 60L);
	pdtt_->tdh = (TDH)(ds_ / 60L);
	}
else	{
	pdtt_->tdh =
	pdtt_->thm =
	pdtt_->tms = 0;
	}
return( pdtt_ );
}


//$ PdttOsUTCPdtt ------------------------------------------------------
// rendszeróra
PDTT		PdttOsUTCPdtt( pdtt_ )
PDTT		pdtt_;
{
struct tm	tmUT;
time_t		tUT;

time( &tUT );
gmtime_r( &tUT, &tmUT );

pdtt_->tdh = tmUT.tm_hour;
pdtt_->thm = tmUT.tm_min;
pdtt_->tms = tmUT.tm_sec;

return( pdtt_ );
}


//$ RChkPdt ------------------------------------------------------------
// dátumidő ellenőrzése
R		RChkPdt( pdt_ )
PDT		pdt_;
{
return( RChkPdtd( &(pdt_->dtd ) ) != rSucceed ||
	RChkPdtt( &(pdt_->dtt ) ) != rSucceed
	// || ( pdt_->dsZ < dsZFirst ) || ( pdt_->dsZ > dsZLast )
	? rFail : rSucceed );
}


//$ RChkPdtd -----------------------------------------------------------
// dátum ellenőrzése
R		RChkPdtd( pdtd_ )
PDTD		pdtd_;
{
return( ( pdtd_->dy > dyLim ) ||
	( pdtd_->dym < dymFirst ) ||
	( pdtd_->dym > dymLim ) ||
	( pdtd_->dmd < dmdFirst ) ||
	( pdtd_->dmd > dmdLenDylDym[ DylFromDy( pdtd_->dy ) ][ pdtd_->dym ] )
	? rFail : rSucceed );
}


//$ RChkPdtt -----------------------------------------------------------
//  idő ellenőrzése
R		RChkPdtt( pdtt_ )
PDTT		pdtt_;
{
return( ( pdtt_->tdh > tdh24Lim ) ||
	( pdtt_->thm > thmLim ) ||
	( pdtt_->tms > tmsLim )
	? rFail : rSucceed );
}


//$ SzOsUTCSzSzSzSz ----------------------------------------------------
SZ	SzOsUTCSzSzSzSz( sz_, szd_, szm_, szt_ )
SZ	sz_;
SZ	szd_;
SZ	szm_;
SZ	szt_;
{
DT	dt;
return( SzSzPdtSzSzSz( sz_, PdtOsUTCPdt( &dt ), szd_, szm_, szt_ ) );
}


//$ SzSzPdtdSz ---------------------------------------------------------
SZ	SzSzPdtdSz( sz_, p_, szd_ )
SZ	sz_;
PDTD	p_;
SZ	szd_;
{
sprintf( sz_, "%04d%s%02d%s%02d",
	p_->dy, szd_, p_->dym, szd_, p_->dmd );
return( sz_ );
}


//$ SzSzPdtSzSzSz ------------------------------------------------------
SZ	SzSzPdtSzSzSz( sz_, p_, szd_, szm_, szt_ )
SZ	sz_;
PDT	p_;
SZ	szd_;
SZ	szm_;
SZ	szt_;
{
sprintf( sz_, "%04d%s%02d%s%02d%s%02d%s%02d%s%02d",
	p_->dtd.dy,  szd_, p_->dtd.dym, szd_, p_->dtd.dmd,
	szm_,
	p_->dtt.tdh, szt_, p_->dtt.thm, szt_, p_->dtt.tms );
return( sz_ );
}


//$ SzSzPdttSz ---------------------------------------------------------
SZ	SzSzPdttSz( sz_, p_, szt_ )
SZ	sz_;
PDTT	p_;
SZ	szt_;
{
sprintf( sz_, "%02d%s%02d%s%02d",
	p_->tdh, szt_, p_->thm, szt_, p_->tms );
return( sz_ );
}


//$ VPdyPddDdDdDd ------------------------------------------------------
// nap és év részszámítás, szökőévekkel
V		VPdyPddDdDdDd( pdy_, pdd_, dd1_, dd2_, dd3_ )
PDY		pdy_;
PDD		pdd_;
DD		dd1_;
DD		dd2_;
DD		dd3_;
{
if ( *pdd_<dd2_ )
	if ( *pdd_<dd1_ )
		*pdy_ = 0;
	else	{
		*pdy_ = 1;
		*pdd_ -= dd1_;
		}
	else	if ( *pdd_<dd3_ )
			{
			*pdy_ = 2;
			*pdd_ -= dd2_;
			}
		else	{
			*pdy_ = 3;
			*pdd_ -= dd3_;
			}
}


//$ WSignPdtdmmPdtd ----------------------------------------------------
// dátum intervallumba esése
// < 0 ha *pdtd_ < pdtdmm_->dtdMin,
// == 0 ha pdtdmm_->dtdMin <= *pdtd_ <= pdtdmm_->dtdMax
// > 0 ha pdtdmm_->dtdMax < *pdtd_
W		WSignPdtdmmPdtd( pdtdmm_, pdtd_ )
PDTDMM		pdtdmm_;
PDTD		pdtd_;
{
if( WSignPdtdPdtd( pdtd_, &pdtdmm_->dtdMin )<0 )
	return( -1 );
else	if( WSignPdtdPdtd( pdtd_, &pdtdmm_->dtdMax )>0 )
		return( 1 );
	else	return( 0 );
}


//$ WSignPdtdPdtd ------------------------------------------------------
// két dátum összehasonlítása
W		WSignPdtdPdtd( pdtd0_, pdtd1_ )
PDTD		pdtd0_;
PDTD		pdtd1_;
{
W		w;

if( (w=(W)pdtd0_->dy -(W)pdtd1_->dy )==0 )
	if( (w=(W)pdtd0_->dym-(W)pdtd1_->dym)==0 )
		w=(W)pdtd0_->dmd-(W)pdtd1_->dmd;
return( w );
}


//$ WSignPdtPdt --------------------------------------------------------
//  két dátumidő összehasonlítása ( 0_ - 1_ )
// ( ret > 0 ) == ( dt0_ >  dt1_ )
W		WSignPdtPdt( pdt0_, pdt1_ )
PDT		pdt0_;
PDT		pdt1_;
{
W		w;

if( (w=(W)pdt0_->dtd.dy -(W)pdt1_->dtd.dy )==0 )
	if( (w=(W)pdt0_->dtd.dym-(W)pdt1_->dtd.dym)==0 )
		if( (w=(W)pdt0_->dtd.dmd-(W)pdt1_->dtd.dmd)==0 )
			if( (w=(W)pdt0_->dtt.tdh-(W)pdt1_->dtt.tdh)==0 )
				if( (w=(W)pdt0_->dtt.thm-(W)pdt1_->dtt.thm)==0 )
					w=(W)pdt0_->dtt.tms-(W)pdt1_->dtt.tms;
return( w );
}


//$ WSignPdttPdtt ------------------------------------------------------
// két idő összehasonlítása
W		WSignPdttPdtt( pdtt0_, pdtt1_ )
PDTT		pdtt0_;
PDTT		pdtt1_;
{
W		w;

if( (w=(W)pdtt0_->tdh-(W)pdtt1_->tdh)==0 )
	if( (w=(W)pdtt0_->thm-(W)pdtt1_->thm)==0 )
		w=(W)pdtt0_->tms-(W)pdtt1_->tms;
return( w );
}


//@

