
///////////////////////////////////////////////////////////
//                                                       //
//                         SAGA                          //
//                                                       //
//      System for Automated Geoscientific Analyses      //
//                                                       //
//                     Tool Library                      //
//                      table_tools                      //
//                                                       //
//-------------------------------------------------------//
//                                                       //
//           table_change_datetime_format.cpp            //
//                                                       //
//                 Copyright (C) 2025 by                 //
//                  Justus Spitzmueller                  //
//                                                       //
//-------------------------------------------------------//
//                                                       //
// This file is part of 'SAGA - System for Automated     //
// Geoscientific Analyses'. SAGA 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.       //
//                                                       //
// SAGA 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, see   //
// <http://www.gnu.org/licenses/>.                       //
//                                                       //
//-------------------------------------------------------//
//                                                       //
//    e-mail:     j.spitzmueller@posteo.de               //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
#include "table_datetime.h"


///////////////////////////////////////////////////////////
//														 //
//														 //
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CTable_Change_DateTime_Format::CTable_Change_DateTime_Format(void)
{
	Set_Name		(_TL("Change Date and Time Format"));

	Set_Author 		(SG_T("J. Spitzm\u00FCller \u00A9 2025"));

	Set_Version 	("Beta");

		// Examples are created with this ISO Date: 2025-07-16T14:32:46 
		// And this format:
		// %a %A %b %B %c %C %d %D %e %F %g %G %h %H %I %j %m %M %n %p %r %R %S %t %T %u %U %V %w %W %x %X %y %Y %z
		// Produced this output by this tool :) Note the newline and tab :D
		// Wed Wednesday Jul July Wed 16 Jul 2025 14:32:46 CEST 20 16 07/16/25 16 2025-07-16 25 2025 Jul 14 02 197 07 32 
 		// pm  2:32:46 pm CEST 14:32 46 	 14:32:46 3 28 29 3 28 16/07/25 14:32:46 25 2025 +0200\n
	Set_Description	(_TW(
		"<p>"
		"This tool converts various date and time formats into other date and time formats."
		"</p>"
		"<p>"
		"Supported input types:"
		"<ul>"
    	"<li>Formatted string</li>"
    	"<li>SAGA date field</li>"
    	"<li><a href=\"https://en.wikipedia.org/wiki/Julian_day#Julian_day_numbers\">Julian Day Number</a></li>"
    	"<li><a href=\"https://en.wikipedia.org/wiki/Julian_day#Variants\">Modified Julian Day Number</a></li>"
    	"<li><a href=\"https://en.wikipedia.org/wiki/Unix_time\">Unix timestamp</a></li>"
    	"<li>Or a combination of components from different fields</li>"
		"</ul>"
		"</p>"
		"<p>"
		"Supported output types:"
		"<ul>"
    	"<li>Formatted string</li>"
    	"<li>SAGA date field</li>"
    	"<li>Julian Day Number</li>"
    	"<li>Modified Julian Day Number</li>"
    	"<li>Unix timestamp</li>"
    	"<li>Or single components</li>"
		"</ul>"
		"</p>"
		"<p>"
		"For formatted strings, the tool uses <a href=\"https://www.gnu.org/software/libc/manual/html_node/Formatting-Calendar-Time.html\"><code>strftime</code></a> "
		"syntax to read from and write to text. "
		"In the GUI, users can select an example format string to quickly apply common formats, "
		"which can then be customized as needed.\n"
		"JDN, MJD, and Unix timestamps are expected in UTC as input and are also returned in UTC. All other operations are performed in local time."
		"</p>"
		"<p>"
		"<table border=\"0\">"
		"<tr><th>Specifier</th><th>Replaced by</th><th>Example</th></tr>"
		"<tr><td><code>%a</code></td><td>Abbreviated weekday name *</td><td><code>Wed</code></td></tr>"
		"<tr><td><code>%A</code></td><td>Full weekday name *</td><td><code>Wednesday</code></td></tr>"
		"<tr><td><code>%b</code></td><td>Abbreviated month name *</td><td><code>Jul</code></td></tr>"
		"<tr><td><code>%B</code></td><td>Full month name *</td><td><code>July</code></td></tr>"
		"<tr><td><code>%c</code></td><td>Preferred date and time representation *</td><td><code>Wed 16 Jul 2025 14:32:46 CEST</code></td></tr>"
		"<tr><td><code>%C</code></td><td>Century (year / 100)</td><td><code>20</code></td></tr>"
		"<tr><td><code>%d</code></td><td>Day of the month, zero-padded (01-31)</td><td><code>16</code></td></tr>"
		"<tr><td><code>%D</code></td><td>Date using the format MM/DD/YY, equivalent to %m/%d/%y</td><td><code>07/16/25</code></td></tr>"
		"<tr><td><code>%e</code></td><td>Day of the month, space-padded ( 1-31)</td><td><code>16</code></td></tr>"
		"<tr><td><code>%F</code></td><td>ISO date YYYY-MM-DD, equivalent to %Y-%m-%d</td><td><code>2025-07-16</code></td></tr>"
		"<tr><td><code>%g</code></td><td>Week-based year, last two digits (00-99)</td><td><code>25</code></td></tr>"
		"<tr><td><code>%G</code></td><td>Full week-based year</td><td><code>2025</code></td></tr>"
		"<tr><td><code>%h</code></td><td>Abbreviated month name, equivalent to %b *</td><td><code>Jul</code></td></tr>"
		"<tr><td><code>%H</code></td><td>Hour in 24-hour format (00-23)</td><td><code>14</code></td></tr>"
		"<tr><td><code>%I</code></td><td>Hour in 12-hour format (01-12)</td><td><code>02</code></td></tr>"
		"<tr><td><code>%j</code></td><td>Day of the year (001-366)</td><td><code>197</code></td></tr>"
		"<tr><td><code>%m</code></td><td>Month as number (01-12)</td><td><code>07</code></td></tr>"
		"<tr><td><code>%M</code></td><td>Minute (00-59)</td><td><code>32</code></td></tr>"
		"<tr><td><code>%n</code></td><td>Newline character (\\n)</td><td><code>""</code></td></tr>"
		"<tr><td><code>%p</code></td><td>AM/PM indicator</td><td><code>pm</code></td></tr>"
		"<tr><td><code>%r</code></td><td>12-hour time format *</td><td><code>2:32:46 pm</code></td></tr>"
		"<tr><td><code>%R</code></td><td>24-hour time (HH:MM), same as %H:%M</td><td><code>14:32</code></td></tr>"
		"<tr><td><code>%S</code></td><td>Second (00-60)</td><td><code>46</code></td></tr>"
		"<tr><td><code>%t</code></td><td>Tab character (\\t)</td><td><code>	</code></td></tr>"
		"<tr><td><code>%T</code></td><td>Time in HH:MM:SS format, same as %H:%M:%S</td><td><code>14:32:46</code></td></tr>"
		"<tr><td><code>%u</code></td><td>Weekday number, Monday=1st day (1-7)</td><td><code>3</code></td></tr>"
		"<tr><td><code>%U</code></td><td>Week number, Sunday=1st day (00-53)</td><td><code>28</code></td></tr>"
		"<tr><td><code>%V</code></td><td>ISO week number (01-53)</td><td><code>29</code></td></tr>"
		"<tr><td><code>%w</code></td><td>Weekday number, Sunday=1st day (0-6)</td><td><code>3</code></td></tr>"
		"<tr><td><code>%W</code></td><td>Week number, Monday=1st day (00-53)</td><td><code>28</code></td></tr>"
		"<tr><td><code>%x</code></td><td>Preferred date format *</td><td><code>16/07/25</code></td></tr>"
		"<tr><td><code>%X</code></td><td>Preferred time format *</td><td><code>14:32:46</code></td></tr>"
		"<tr><td><code>%y</code></td><td>Year, last two digits (00-99)</td><td><code>25</code></td></tr>"
		"<tr><td><code>%Y</code></td><td>Full year (4-digit)</td><td><code>2025</code></td></tr>"
		"<tr><td><code>%z</code></td><td>ISO Numeric time zone offset (e.g., +0200)</td><td><code>+0200</code></td></tr>"
		"<tr><td><code>%Z</code></td><td>Time zone name or abbreviation (empty if zone can not determined) *</td><td><code>CEST</code></td></tr>"
		"<tr><td><code>%%</code></td><td>A literal percent sign (%)</td><td><code>%</code></td></tr>"
		"</table>"
		"* The specifiers marked with an asterisk (*) are locale-dependent."
		"</p>"
		"<p>"
		"The output field type ist <code>string</code> for formatted string, <code>date</code> for saga date field, "
		"<code>double</code> for JDN and MJD, <code>signed long</code> for unix timestamp and <code>unsigned short</code> "
		"for the individual components exept year (<code>signed int</code>). "
		"</p>"
	));
	



	Add_Reference( "https://man.archlinux.org/man/strftime.3.en", SG_T("strftime() Man-Page at archlinux.org"));
	Add_Reference( "https://www.gnu.org/software/libc/manual/html_node/Formatting-Calendar-Time.html", SG_T("Formatting Calendar Time - The GNU C Library"));
	Add_Reference( "https://en.wikipedia.org/wiki/Julian_day#Julian_day_numbers", SG_T("Julian day numbers - Wikipedia"));
	Add_Reference( "https://en.wikipedia.org/wiki/Julian_day#Variants", SG_T("Modified JD (Variants section of JD Article) - Wikipedia"));
	Add_Reference( "https://en.wikipedia.org/wiki/Unix_time", SG_T("Unix time - Wikipedia"));

	//-----------------------------------------------------
	Parameters.Add_Table("",
		"TABLE"		, _TL("Table"),
		_TL(""),
		PARAMETER_INPUT
	);

	Parameters.Add_Table("",
		"OUTPUT"	, _TL("Output"),
		_TL(""),
		PARAMETER_OUTPUT_OPTIONAL
	);
	
	Parameters.Add_Table_Field("TABLE",
		"FIELD"		, _TL("DateTime Field"),
		_TL("")
	);
	
	Parameters.Add_Info_String("", "TIMEZONE_INFO", _TL("Info: Detected Timezone"), _TL(""), CSG_DateTime().Now().Format("%Z %z"))->Set_UseInCMD(false);

	Parameters.Add_Node("", "INPUT_NODE", "", "");

	Parameters.Add_Choice("INPUT_NODE",
		"FORMAT_IN"	, _TL("Input Format"),
		_TL(""),
		CSG_String::Format("%s|%s|%s|%s|%s|%s",
			_TL("Formatted String"),
			_TL("SAGA Date Field Type"),
			_TL("Julian Day Number (JDN)"),
			_TL("Modified Julian Day Number (MJD)"),
			_TL("Unix Timestamp"),
			_TL("Multiple Fields") 
		)
	);

	Parameters.Add_String("INPUT_NODE",
		"STRING_IN"	, _TL("Input Format String"),
		_TL(""),
		"" 
	);

	Parameters.Add_Choice("INPUT_NODE",
		"EXAMPLE_IN", _TL("Example Format String"),
		_TL(""),
		CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s",
			_TL("<Select a String>"),
			SG_T("{%Y-%m-%dT%H:%M:%S} YYYY-MM-DDTHH:MM:SS (ISO 8601)"),
			SG_T("{%Y-%m-%d} YYYY-MM-DD (SAGA Date Format)"),
			SG_T("{%d.%m.%Y %H:%M:%S} DD.MM.YYYY HH:MM:SS"),
			SG_T("{%m/%d/%Y %I:%M:%S %p} MM/DD/YYYY HH:MM:SS PM/AM"),
			SG_T("{%d:%m:%Y} DD:MM:YYYY"),
			SG_T("{%Y:%m:%d} YYYY:MM:DD"),
			SG_T("{%d:%m:%y} DD:MM:YY"),
			SG_T("{%y;%m;%d} YY;MM;DD")
		)
	)->Set_UseInCMD(false);
	
	Parameters.Add_String("OUTPUT",
		"FIELD_NAME_OUT", _TL("Output Field Name"),
		_TL(""),
		"DateTime"
	);

	Parameters.Add_Node("", "OUTPUT_NODE", "", "");
	
	Parameters.Add_Choice("OUTPUT_NODE",
		"FORMAT_OUT"	, _TL("Output Format"),
		_TL(""),
		CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s",
			_TL("Formatted String"),
			_TL("SAGA Date Field Type"),
			_TL("Julian Day Number (JDN)"),
			_TL("Modified Julian Day Number (MJD)"),
			_TL("Unix Timestamp"),
			_TL("Day of the Year"),
			_TL("Year"),
			_TL("Month"),
			_TL("Day"),
			_TL("Hour"),
			_TL("Minute"),
			_TL("Second"),
			_TL("Millisecond")
		)
	);
	
	Parameters.Add_String("OUTPUT_NODE",
		"STRING_OUT", _TL("Output Format String"),
		_TL(""),
		"" 
	);

	CSG_Parameter *pParameter =
	Parameters.Add_Choice("OUTPUT_NODE",
		"EXAMPLE_OUT", _TL("Example Format String"),
		_TL(""),
		""
	);

	pParameter->asChoice()->Set_Items(Parameters("EXAMPLE_IN")->asChoice()->Get_Items(true));
	pParameter->Set_UseInCMD(false);

	//const SG_Char* S[] = { L"IN", L"OUT"};
	m_Max_Num = has_GUI() ? 7 : 3;
	for( int i=0; i<m_Max_Num; i++ )
	{
		//CSG_String Base = CSG_String::Format("_%s-%d", 	S[i], j);
		CSG_String ID 	= CSG_String::Format("_%d",i  );
		CSG_String Num 	= CSG_String::Format(" %d",i+1);

		CSG_Parameter *pParameter =
		Parameters.Add_Table_Field("TABLE",
			"MULTIPLE_FIELD" + ID, _TL("Field") + Num,
			_TL(""), true
		);
		pParameter->Set_Enabled(false);
		pParameter->Set_Value(-1);
	
		Parameters.Add_Choice("MULTIPLE_FIELD" + ID,
			"MULTIPLE_FORMAT" + ID, _TL("Input Format") + Num,
			_TL(""),
			CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s",
				_TL("Formatted String"),
				_TL("SAGA Date Field Type"),
				_TL("Day of the Year"),
				_TL("Year"),
				_TL("Month"),
				_TL("Day"),
				_TL("Hour"),
				_TL("Minute"),
				_TL("Second"),
				_TL("Millisecond")
			), i+3
		)->Set_Enabled(false);
		
		Parameters.Add_String("MULTIPLE_FIELD" + ID,
			"MULTIPLE_STRING" + ID, _TL("Input String") + Num,
			_TL(""),
			"" 
		)->Set_Enabled(false);

		pParameter =
		Parameters.Add_Choice("MULTIPLE_FIELD" + ID,
			"MULTIPLE_EXAMPLE" + ID, _TL("Example Format String") + Num,
			_TL(""),
			CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s",
				_TL("<Select a String>"),
				SG_T("{%d:%m:%Y} DD:MM:YYYY"),
				SG_T("{%d.%m.%Y} DD.MM.YYYY"),
				SG_T("{%m/%d/%Y} MM/DD/YYYY"),
				SG_T("{%Y:%m:%d} YYYY:MM:DD"),
				SG_T("{%d;%m;%y} DD;MM;YY"),
				SG_T("{%y-%m-%d} YY-MM-DD"),
				SG_T("{%T} HH:MM:SS"),
				SG_T("{%H.%M.%S} HH.MM.SS"),
				SG_T("{%H%M%S} HHMMSS"),
				SG_T("{%I:%M:%S %p} HH:MM:SS PM/AM")
			)
		);
		pParameter->Set_Enabled(false);
		pParameter->Set_UseInCMD(false);
	}



}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
int CTable_Change_DateTime_Format::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
	if( pParameter->Cmp_Identifier("FORMAT_IN" ) )
	{
		pParameters->Set_Enabled("STRING_IN", 			pParameter->asInt() == 0 );
		pParameters->Set_Enabled("EXAMPLE_IN", 			pParameter->asInt() == 0 );
		pParameters->Set_Enabled("MULTIPLE_FIELD_0",  	pParameter->asInt() == 5 );
		pParameters->Set_Enabled("MULTIPLE_FORMAT_0", 	pParameter->asInt() == 5 );
		pParameters->Set_Enabled("FIELD",  				pParameter->asInt() != 5 );
		
		On_Parameter_Changed(pParameters, pParameters->Get_Parameter("MULTIPLE_FORMAT_0"));

		if( pParameter->asInt() != 5 )
		{
			for( int p=0; p<m_Max_Num; p++ )
				pParameters->Set_Enabled(CSG_String::Format("MULTIPLE_FIELD_%d", p),false);
		}
	}

	if( pParameter->Cmp_Identifier("FORMAT_OUT") )
	{
		pParameters->Set_Enabled("STRING_OUT" , pParameter->asInt() == 0 );
		pParameters->Set_Enabled("EXAMPLE_OUT", pParameter->asInt() == 0 );
	}

	return( CSG_Tool::On_Parameters_Enable(pParameters, pParameter) );
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
int CTable_Change_DateTime_Format::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
	if( pParameter->Cmp_Identifier("EXAMPLE_IN") && pParameter->asInt() != 0 )
	{
		pParameters->Get_Parameter("STRING_IN")->Set_Value( pParameter->asChoice()->Get_Data() );
		pParameter->Set_Value(0);
	}

	if( pParameter->Cmp_Identifier("EXAMPLE_OUT") && pParameter->asInt() != 0 )
	{
		pParameters->Get_Parameter("STRING_OUT")->Set_Value( pParameter->asChoice()->Get_Data() );
		pParameter->Set_Value(0);
	}

	if( CSG_String(pParameter->Get_Identifier()).Contains("MULTIPLE") )
	{
		TSG_Parameter_Type Type = pParameter->Get_Type();

		CSG_String ID = pParameter->Get_Identifier(); CSG_String Param = ID.BeforeLast('_'); ID = ID.AfterLast('_');
		SG_Char Num = ID[ID.Length()-1]; ID.Replace_Single_Char(Num,Num+1);

		if( Type == PARAMETER_TYPE_Table_Field )
		{
			if( pParameters->Get_Parameter(Param + "_" + ID))
			{
				pParameters->Get_Parameter(Param + "_" + ID)->Set_Enabled(pParameter->asInt() != -1);
				pParameters->Get_Parameter("MULTIPLE_FORMAT_"+ ID)->Set_Enabled(pParameter->asInt() != -1);
				On_Parameter_Changed(pParameters, pParameters->Get_Parameter("MULTIPLE_FORMAT_"+ ID));

				if( pParameter->asInt() == -1 )
				{
					pParameters->Get_Parameter(Param + "_" + ID)->Set_Value(-1);
					On_Parameter_Changed(pParameters, pParameters->Get_Parameter(Param + "_" + ID));
				}
			}
		}
		
		if( CSG_String(pParameter->Get_Identifier()).Contains("MULTIPLE_FORMAT") )
		{
			pParameters->Set_Enabled("MULTIPLE_STRING_" + CSG_String(Num), pParameter->asInt() == 0 && pParameter->is_Enabled());
			pParameters->Set_Enabled("MULTIPLE_EXAMPLE_"+ CSG_String(Num), pParameter->asInt() == 0 && pParameter->is_Enabled());
		}
		
		if( CSG_String(pParameter->Get_Identifier()).Contains("MULTIPLE_EXAMPLE") )
		{
			pParameters->Get_Parameter("MULTIPLE_STRING_"+ CSG_String(Num))->Set_Value( pParameter->asChoice()->Get_Data() );
			pParameter->Set_Value(0);
		}
	}

	return( CSG_Tool::On_Parameter_Changed(pParameters, pParameter) );
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
bool CTable_Change_DateTime_Format::On_Execute(void)
{
	//-----------------------------------------------------
	CSG_Table	*pTable	= Parameters("OUTPUT")->asTable();

	if( pTable && pTable != Parameters("TABLE")->asTable() )
	{
		pTable->Assign  (Parameters("TABLE")->asTable());
		pTable->Set_Name(Parameters("TABLE")->asTable()->Get_Name());
	}
	else
	{
		pTable	= Parameters("TABLE")->asTable();
	}

	//-----------------------------------------------------
	int	Field_In			= Parameters("FIELD")->asInt();
	int Format_In			= Parameters("FORMAT_IN")->asInt();
	int Format_Out			= Parameters("FORMAT_OUT")->asInt();
	CSG_String String_In 	= Format_In  == 1 ? L"%Y-%m-%d" : Parameters("STRING_IN")->asString();
	CSG_String String_Out 	= Format_Out == 1 ? L"%Y-%m-%d" : Parameters("STRING_OUT")->asString();

	//-----------------------------------------------------
	TSG_Data_Type In_Type = pTable->Get_Field_Type(Field_In);
	CSG_String Prefered_Type = "";
	if( Format_In == 0 && In_Type != SG_DATATYPE_String )
	{
		Prefered_Type = "string";
	}
	if( Format_In == 1 && (In_Type != SG_DATATYPE_String && In_Type != SG_DATATYPE_Date) )
	{
		Prefered_Type = "date";
	}
	if( Format_In == 2 && In_Type != SG_DATATYPE_Double )
	{
		Prefered_Type = "double";
	}
	if( Format_In == 3 && In_Type < SG_DATATYPE_DWord && In_Type > SG_DATATYPE_Long)
	{
		Prefered_Type = "(u)int32 and (u)int64";
	}

	if( !Prefered_Type.is_Empty() )
	{
		Error_Fmt("%s%s%s%s%s%s", _TL("Input format: "), Parameters("FORMAT_IN")->asString(), _TL(" expects field type: "), 
				  Prefered_Type.c_str(), _TL(" and got "), SG_Data_Type_Get_Name(In_Type, true).c_str());
		return( false );
	}
	//-----------------------------------------------------
	TSG_Data_Type Out_Type = SG_DATATYPE_String;
	switch( Format_Out )
	{
		case  0: Out_Type = SG_DATATYPE_String;		break;
		case  1: Out_Type = SG_DATATYPE_Date; 		break;	
		case  2: Out_Type = SG_DATATYPE_Double; 	break;
		case  3: Out_Type = SG_DATATYPE_Double; 	break;
		case  4: Out_Type = SG_DATATYPE_Long; 		break;
		case  5: Out_Type = SG_DATATYPE_Word;		break;
		case  6: Out_Type = SG_DATATYPE_Int; 		break;
		case  7: Out_Type = SG_DATATYPE_Word; 		break;
		case  8: Out_Type = SG_DATATYPE_Word; 		break;
		case  9: Out_Type = SG_DATATYPE_Word;		break;
		case 10: Out_Type = SG_DATATYPE_Word; 		break;
		case 11: Out_Type = SG_DATATYPE_Word; 		break;
		case 12: Out_Type = SG_DATATYPE_Word; 		break;
	}
	pTable->Add_Field(Parameters("FIELD_NAME_OUT")->asString(), Out_Type);
	int Field_Out = pTable->Get_Field_Count()-1;

	//-----------------------------------------------------
	for(sLong iRecord=0; iRecord<pTable->Get_Count() && Set_Progress(iRecord, pTable->Get_Count()); iRecord++)
	{
		CSG_DateTime	Date; Date.Set_Unix_Time(0); Date.Reset_Time();
		CSG_Table_Record *pRecord = pTable->Get_Record(iRecord);

		switch( Format_In )
		{
			// From_UTC() leads to double conversion for JDN/MJD but works for unix. 12:00:00 UTC (14:00:00 CEST) -> 16:00:00 CEST 
			//case 2:	Date.Set( 	pRecord->asDouble(Field_In) 			);	Date = Date.From_UTC(); break;
			//case 3:	Date.Set( 	pRecord->asDouble(Field_In) + 2400000.5	);	Date = Date.From_UTC(); break;
			case 0: 
			case 1: Date.Parse_Format( 	pRecord->asString(Field_In), String_In 	);				break;
			case 2:	Date.Set( 			pRecord->asDouble(Field_In) 			);				break;
			case 3:	Date.Set( 			pRecord->asDouble(Field_In) + 2400000.5	);				break;
			case 4:	Date.Set_Unix_Time( pRecord->asLong(  Field_In) 			).From_UTC(); 	break;
			case 5:	
			{
				for( int p=0; p<m_Max_Num; p++ )
				{
					CSG_Parameter *pField = Parameters(CSG_String::Format("MULTIPLE_FIELD_%d", p));
					int Multi_Field = pField->asInt();

					if( Multi_Field != -1 )
					{
						int 		Multi_Format_In = Parameters(CSG_String::Format("MULTIPLE_FORMAT_%d", p))->asInt();
						CSG_String 	Multi_String_In = Multi_Format_In  == 1 ? L"%Y-%m-%d" : Parameters(CSG_String::Format("MULTIPLE_STRING_%d", p))->asString();
					
						switch( Multi_Format_In )
						{
							case 0: 
							case 1: Date.Parse_Format( 		pRecord->asString(	Multi_Field), Multi_String_In 	);	break;
							case 2:	Date.Set_DayOfYear( 	pRecord->asShort(	Multi_Field) 					);	break;
							case 3:	Date.Set_Year(			pRecord->asInt(		Multi_Field) 					);	break;
							case 4:	Date.Set_Month( 		pRecord->asShort(  	Multi_Field) - 1 				);	break; // wx/SAGA uses a enum starting at 0
							case 5:	Date.Set_Day( 			pRecord->asShort(  	Multi_Field) 					);	break;
							case 6:	Date.Set_Hour( 			pRecord->asDouble(	Multi_Field) 					);	break;
							case 7:	Date.Set_Minute( 		pRecord->asShort(  	Multi_Field) 					);	break;
							case 8:	Date.Set_Second( 		pRecord->asShort(  	Multi_Field) 					);	break;
							case 9:	Date.Set_Millisecond( 	pRecord->asShort(  	Multi_Field) 					);	break;
						}
					}
				}
			}
			break;
		}

		if( !Date.is_Valid() )
		{
			Error_Set( CSG_String::Format( "DateTime is not valid. Table record: %lld. DateTime as unix timestamp: %lld", iRecord, Date.Get_Unix_Time()) ); 
			return( false );
		}

		switch( Format_Out )
		{
			case  0: 
			case  1: pRecord->Set_Value( Field_Out, Date.Format(String_Out) );	break;
			case  2: pRecord->Set_Value( Field_Out, Date.Get_JDN()			); 	break;
			case  3: pRecord->Set_Value( Field_Out, Date.Get_MJD()			); 	break;
			case  4: pRecord->Set_Value( Field_Out, Date.Get_Unix_Time()	); 	break;
			case  5: pRecord->Set_Value( Field_Out, Date.Get_DayOfYear() 	);	break;
			case  6: pRecord->Set_Value( Field_Out, Date.Get_Year()			); 	break;
			case  7: pRecord->Set_Value( Field_Out, Date.Get_Month() + 1	); 	break; // wx/SAGA uses a enum starting by 0
			case  8: pRecord->Set_Value( Field_Out, Date.Get_Day()			); 	break;
			case  9: pRecord->Set_Value( Field_Out, Date.Get_Hour() 		);	break;
			case 10: pRecord->Set_Value( Field_Out, Date.Get_Minute()		); 	break;
			case 11: pRecord->Set_Value( Field_Out, Date.Get_Second()		); 	break;
			case 12: pRecord->Set_Value( Field_Out, Date.Get_Millisecond()	); 	break;
		}
	}

	//-----------------------------------------------------
	if( pTable == Parameters("TABLE")->asTable() )
	{
		DataObject_Update(pTable);
	}

	return( true );
}

///////////////////////////////////////////////////////////
//														 //
//														 //
//														 //
///////////////////////////////////////////////////////////

CDateTime_Base::CDateTime_Base(void)
{
	//-----------------------------------------------------
	Parameters.Add_Table("",
		"TABLE"		, _TL("Table"),
		_TL(""),
		PARAMETER_INPUT
	);


}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
void CDateTime_Base::Set_Enable_DateTime(CSG_Parameters *pParameters, CSG_String Identifier, bool Enable)
{
	pParameters->Get_Parameter("NODE_"+Identifier)->Set_Enabled(Enable);

	if( Enable == false )
	{
		pParameters->Get_Parameter("FIELD_"+Identifier)->Set_Enabled(false);
	}
	else
	{
		On_Parameters_Enable( pParameters, pParameters->Get_Parameter("FORMAT_"+Identifier) );
	}
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
int CDateTime_Base::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
	CSG_String Name = pParameter->Get_Identifier();
	if( Name.Contains("FORMAT_") )
	{
		CSG_String Id = Name.AfterFirst('_');
		pParameters->Set_Enabled("DATE_"  + Id, pParameter->asInt() <= 1 );
		pParameters->Set_Enabled("TIME_"  + Id, pParameter->asInt() == 1 );
		pParameters->Set_Enabled("FIELD_" + Id, pParameter->asInt() >= 2 );
	}

	return( CSG_Tool::On_Parameters_Enable(pParameters, pParameter) );
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
int CDateTime_Base::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
	return( CSG_Tool::On_Parameter_Changed(pParameters, pParameter) );
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_DateTime CDateTime_Base::Get_DateTime(CSG_String Identifier, CSG_Table_Record *pRecord)
{
	CSG_DateTime  TimePoint; TimePoint.Set_Unix_Time(0);

	CSG_Parameter *pChoice 	= Parameters("FORMAT_" + Identifier), *pDate 	= Parameters("DATE_" + Identifier),
				  *pTime 	= Parameters("TIME_"   + Identifier), *pField 	= Parameters("FIELD_"+ Identifier),
				  *pISOTime = Parameters("ISOTIME_"+ Identifier);

	if( pChoice )
	{
		if( pChoice->asInt() <= 1 && has_GUI() && pDate )
		{
			TimePoint = pDate->asDate()->Get_Date(); 
		}
		if( pChoice->asInt() == 1 && has_GUI() && pTime )
		{
			TimePoint.Parse_Format(pTime->asString(), "%T");	
		}
		if( pChoice->asInt() <= 1 && has_CMD() && pISOTime )
		{
			if(!TimePoint.Parse_ISOCombined(pISOTime->asString()))
				TimePoint.Parse_ISODate    (pISOTime->asString());
		}
		if( pChoice->asInt() == 0 && has_CMD() && pISOTime )
		{
			TimePoint.Reset_Time();
		}
		if( pChoice->asInt() == 2 && pRecord && pField )
		{
			TimePoint.Parse_Format( pRecord->asString(pField->asInt()), "%F" );	
		}
		if( pChoice->asInt() == 3 && pRecord && pField )
		{
			TimePoint.Set( pRecord->asDouble(pField->asInt()) );
		}
		if( pChoice->asInt() == 4 && pRecord && pField )
		{
			TimePoint.Set( pRecord->asDouble(pField->asInt()) + 2400000.5 );
		}
		if( pChoice->asInt() == 5 && pRecord && pField )
		{
			TimePoint.Set_Unix_Time( pRecord->asLong(pField->asInt()) ).From_UTC();
		}
	}
	
	return( TimePoint );
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
bool CDateTime_Base::Check_DateTime_Parameter(CSG_String Identifier, CSG_String &Error_Message)
{
	CSG_Parameter *pChoice 	= Parameters("FORMAT_" + Identifier), *pDate 	= Parameters("DATE_" + Identifier),
				  *pTime 	= Parameters("TIME_"   + Identifier), *pField 	= Parameters("FIELD_"+ Identifier),
				  *pISOTime = Parameters("ISOTIME_"+ Identifier);

	if( !pChoice || !pDate || !pTime || !pField || !pISOTime )
	{
		Error_Message = _TL("Some Parameter(s) of the base class is missing");
		return( false );
	}


	CSG_Table *pTable = Parameters("TABLE")->asTable();
	TSG_Data_Type Type = pTable->Get_Field_Type(pField->asInt());

	CSG_DateTime TimePoint;

	if( pChoice->asInt() == 1 && has_GUI() )
	{
		if( !TimePoint.Parse_Format(pTime->asString(), "%T") )
		{
			Error_Message = "Cannot parse input time. Please provide the time in the format \"HH:MM:SS\"";
			return( false );
		}
	}
	if( pChoice->asInt() <= 1 && has_CMD() )
	{
		if(	!TimePoint.Parse_ISOCombined(pISOTime->asString())
		&&	!TimePoint.Parse_ISODate    (pISOTime->asString()) )
		{	
			Error_Message = "Cannot parse input date/time. Please provide the date/time in the ISO format \"YYYY-MM-DDTHH:MM:SS\" or \"YYYY-MM-DD\"";
			return( false );
		}
	}
	if( pChoice->asInt() == 2 && Type != SG_DATATYPE_String && Type != SG_DATATYPE_Date )
	{
		Error_Message = "The selected field must be type of string or date for saga date field type";
	}
	
	if( pChoice->asInt() == 3 || pChoice->asInt() == 4)
	{
		if( Type != SG_DATATYPE_Double )
		{
			Error_Message = "The selected field must be of type double for JDN or MJD";
			return( false );
		}
	}
	if( pChoice->asInt() == 5 && Type != SG_DATATYPE_Long )
	{
		Error_Message = "The selected field must be of type long for unix timestamp";
		return( false );
	}
	return( true );
}
		
///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
bool CDateTime_Base::Add_DateTime_Parameter(CSG_String Identifier, CSG_String Name, double JDN_Offset )
{
	Parameters.Add_Table_Field("TABLE",
		"FIELD_" + Identifier	, Name + _TL(" Field"),
		_TL("")
	);
	
	Parameters.Add_Node("",
		"NODE_" + Identifier, Name,
		_TL("")
	);
	
	Parameters.Add_Choice("NODE_" + Identifier,
		"FORMAT_" + Identifier, Name + _TL("Format "),
		_TL(""),
		CSG_String::Format("%s|%s|%s|%s|%s|%s",
			_TL("Set Date"),
			_TL("Set Date and Time"),
			_TL("SAGA Date Field Type"),
			_TL("Julian Day Number (JDN)"),
			_TL("Modified Julian Day Number (MJD)"),
			_TL("Unix Timestamp")
		)
	);

	Parameters.Add_Date("NODE_" + Identifier,
		"DATE_" + Identifier, Name + _TL(" Date"),
		_TL(""), CSG_DateTime().Now().Get_JDN() + JDN_Offset
	)->Set_UseInCMD(false);
	
	Parameters.Add_String("NODE_" + Identifier,
		"TIME_" + Identifier, Name + _TL(" Time"),
		_TL(""), CSG_DateTime().Now().Format("%T")
	)->Set_UseInCMD(false);
	
	Parameters.Add_String("NODE_" + Identifier,
		"ISOTIME_" + Identifier, Name + _TL(" ISO Time"),
		_TL(""), CSG_DateTime().Now().Format("%FT%T")
	)->Set_UseInGUI(false);

	return( true );
}

///////////////////////////////////////////////////////////
//														 //
//														 //
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CDateTime_Difference::CDateTime_Difference(void)
{
	Set_Name		(_TL("Date and Time Difference"));

	Set_Author 		(SG_T("J. Spitzm\u00FCller \u00A9 2025"));

	Set_Version 	("Beta");

	Set_Description	(_TW(
		"<p>"
		"This tool converts various date and time formats into other date and time formats."
		"</p>"
		"<p>"
		"Supported input types:"
		"<ul>"
    	"<li>Formatted string</li>"
    	"<li>SAGA date field</li>"
    	"<li><a href=\"https://en.wikipedia.org/wiki/Julian_day#Julian_day_numbers\">Julian Day Number</a></li>"
    	"<li><a href=\"https://en.wikipedia.org/wiki/Julian_day#Variants\">Modified Julian Day Number</a></li>"
    	"<li><a href=\"https://en.wikipedia.org/wiki/Unix_time\">Unix timestamp</a></li>"
    	"<li>Or a combination of components from different fields</li>"
		"</ul>"
		"</p>"
		"<p>"
		"<table border=\"0\">"
		"<tr><th>Specifier</th><th>Replaced by</th></tr>"
    	"<tr><td><code>%H</code></td><td>Number of Hours</td></tr>"
    	"<tr><td><code>%M</code></td><td>Number of Minutes</td></tr>"
    	"<tr><td><code>%S</code></td><td>Number of Seconds</td></tr>"
    	"<tr><td><code>%l</code></td><td>Number of Milliseconds</td></tr>"
    	"<tr><td><code>%D</code></td><td>Number of Days</td></tr>"
    	"<tr><td><code>%E</code></td><td>Number of Weeks</td></tr>"
    	"<tr><td><code>%%</code></td><td>The percent character</td></tr>"
		"</table>"
		"</p>"
		"<p>"
		"Note that, for example, the number of hours in the description above is not well defined: it can be either the total "
		"number of hours (for example, for a time span of 50 hours this would be 50) or just the hour part of the time span, "
		"which would be 2 in this case as 50 hours is equal to 2 days and 2 hours."
		"wxTimeSpan resolves this ambiguity in the following way: if there had been, indeed, the D format specified preceding "
		"the H, then it is interpreted as 2. Otherwise, it is 50.\n"
		"The same applies to all other format specifiers: if they follow a specifier of larger unit, only the rest part is taken, "
		"otherwise the full value is used."
	));

	Add_DateTime_Parameter("TIMEPOINT", "Timepoint");
	Add_DateTime_Parameter("SUBTRAHENT","Subtrahent");

	Parameters.Add_Table("",
		"OUTPUT"	, _TL("Output"),
		_TL(""),
		PARAMETER_OUTPUT_OPTIONAL
	);

	//-----------------------------------------------------
	Parameters.Add_Choice("",
		"OUTPUT_AS", _TL("Output as"),
		_TL(""),
		CSG_String::Format("%s|%s|%s|%s|%s|%s|%s",
			_TL("Format"),
			_TL("Weeks"),
			_TL("Days"),
			_TL("Hours"),
			_TL("Minutes"),
			_TL("Seconds"),
			_TL("Milliseconds")
		)
	);

	Parameters.Add_String("OUTPUT",
		"FORMAT_STRING", _TL("Format String"),
		_TL(""), ""
	);

	Parameters.Add_Bool("",
		"ABSOLUTE", _TL("Make Timespan Absolute"),
		_TL(""), false 
	);

	

}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
int CDateTime_Difference::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
	if( pParameter->Cmp_Identifier("OUTPUT") )
	{
		pParameters->Set_Enabled("FORMAT_STRING", pParameter->asInt() == 0);
	}

	return( CDateTime_Base::On_Parameters_Enable(pParameters, pParameter) );
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
int CDateTime_Difference::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
	return( CDateTime_Base::On_Parameter_Changed(pParameters, pParameter) );
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
bool CDateTime_Difference::On_Execute(void)
{
	CSG_Table *pTable = Parameters("OUTPUT")->asTable();
	
	if( pTable && pTable != Parameters("TABLE")->asTable() )
	{
		pTable->Assign  (Parameters("TABLE")->asTable());
		pTable->Set_Name(Parameters("TABLE")->asTable()->Get_Name());
	}
	else
	{
		pTable	= Parameters("TABLE")->asTable();
	}

	bool Absolute = Parameters("ABSOLUTE")->asBool();
	int Output = Parameters("OUTPUT_AS")->asInt();

	pTable->Add_Field( Parameters("OUTPUT_AS")->asChoice()->asString(), Output == 0 ? SG_DATATYPE_String : SG_DATATYPE_Long );
	int Field = pTable->Get_Field_Count()-1;
	CSG_String Format = Parameters("FORMAT_STRING")->asString();

	for( sLong i=0; i<pTable->Get_Count(); i++ )
	{
		CSG_Table_Record *pRecord = pTable->Get_Record(i);

		CSG_DateTime Timepoint 	= Get_DateTime("TIMEPOINT",  pRecord);
		CSG_DateTime Subtrahent = Get_DateTime("SUBTRAHENT", pRecord);

		CSG_TimeSpan Timespan = Timepoint.Subtract(Timepoint);

		if( Absolute )
			Timespan.Abs();
		
		switch( Output )
		{
			case  0: pRecord->Set_Value( Field, Timespan.Format(Format) 	);	break;
			case  1: pRecord->Set_Value( Field, Timespan.Get_Weeks() 		);	break;
			case  2: pRecord->Set_Value( Field, Timespan.Get_Days() 		); 	break;
			case  3: pRecord->Set_Value( Field, Timespan.Get_Hours()		); 	break;
			case  4: pRecord->Set_Value( Field, Timespan.Get_Minutes()		); 	break;
			case  5: pRecord->Set_Value( Field, Timespan.Get_Seconds() 		);	break;
			case  6: pRecord->Set_Value( Field, Timespan.Get_Milliseconds() ); 	break;
		}
	}
	
	//-----------------------------------------------------
	if( pTable == Parameters("TABLE")->asTable() )
	{
		DataObject_Update(pTable);
	}

	return( true );
}

///////////////////////////////////////////////////////////
//														 //
//														 //
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CDateTime_Logic::CDateTime_Logic(void)
{
	Set_Name		(_TL("Date and Time Logic"));

	Set_Author 		(SG_T("J. Spitzm\u00FCller \u00A9 2025"));

	Set_Version 	("Beta");

	Parameters.Add_Table("",
		"OUTPUT"	, _TL("Output"),
		_TL(""),
		PARAMETER_OUTPUT_OPTIONAL
	);

	Add_DateTime_Parameter("TIMEPOINT", "Timepoint");


	//-----------------------------------------------------
	Parameters.Add_Node("", "NODE", _TL("Operation"), _TL(""));

	Parameters.Add_Choice("NODE",
		"OPERATION", _TL("Logical Operation"),
		_TL(""),
		CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s",
			_TL("{Earlier}Is Earlier Than"),
			_TL("{Equal}Is Equal To"),
			_TL("{Later}Is Later Than"),
			_TL("{Same}Is Same Date"),
			_TL("{Same}Is Same Time"),
			_TL("{Between}Is Between"),
			_TL("{Between}Is Strictly Between"),
			_TL("{Leap}Is Leap Year"),
			_TL("{DST}Is Daylight Saving Time")
		)
	);

	Parameters.Add_Choice("NODE",
		"BOOL_AS", _TL("Output"),
		_TL(""),
		CSG_String::Format("%s|%s",
			_TL("Bool"),
			_TL("String")
		)
	);

	Parameters.Add_String("NODE",
		"TRUE_STRING", _TL("True String"),
		_TL(""), "true"
	);

	Parameters.Add_String("NODE",
		"FALSE_STRING", _TL("False String"),
		_TL(""), "false"
	);
	
	//-----------------------------------------------------
	Add_DateTime_Parameter("OTHER",		"Other");
	Add_DateTime_Parameter("BEGIN",		"Range Begin");
	Add_DateTime_Parameter("END",		"Range End");
	
}


///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
int CDateTime_Logic::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
	if( pParameter->Cmp_Identifier("BOOL_AS") )
	{
		pParameters->Set_Enabled( "TRUE_STRING", pParameter->asInt() == 1);
		pParameters->Set_Enabled("FALSE_STRING", pParameter->asInt() == 1);
	}
	
	if( pParameter->Cmp_Identifier("OPERATION") )
	{
		Set_Enable_DateTime(pParameters, "OTHER", pParameter->asInt() <= 4  );
		Set_Enable_DateTime(pParameters, "BEGIN", pParameter->asInt() == 5 || pParameter->asInt() == 6 );
		Set_Enable_DateTime(pParameters, "END"	, pParameter->asInt() == 5 || pParameter->asInt() == 6 );
	}
	
	return( CDateTime_Base::On_Parameters_Enable(pParameters, pParameter) );
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
int CDateTime_Logic::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
{
	return( CDateTime_Base::On_Parameter_Changed(pParameters, pParameter) );
}

///////////////////////////////////////////////////////////
//														 //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
bool CDateTime_Logic::On_Execute(void)
{
	CSG_Table *pTable = Parameters("TABLE")->asTable();
	
	if( pTable && pTable != Parameters("TABLE")->asTable() )
	{
		pTable->Assign  (Parameters("TABLE")->asTable());
		pTable->Set_Name(Parameters("TABLE")->asTable()->Get_Name());
	}
	else
	{
		pTable	= Parameters("TABLE")->asTable();
	}

	CSG_String Error_Message = "";
	
	if( !Check_DateTime_Parameter("TIMEPOINT"	, Error_Message )
	||  !Check_DateTime_Parameter("OTHER"		, Error_Message )
	||  !Check_DateTime_Parameter("BEGIN"		, Error_Message )
	||  !Check_DateTime_Parameter("END"			, Error_Message ) )
	{
		Error_Set( Error_Message );
		return( false );
	}

	int Output 		= Parameters("OUTPUT")->asInt();
	int Operation 	= Parameters("OPERATION")->asInt();
	CSG_String True = Parameters("TRUE_STRING")->asString(), False = Parameters("FALSE_STRING")->asString();

	pTable->Add_Field( Parameters("OPERATION")->asChoice()->Get_Data(), Output == 0 ? SG_DATATYPE_Word : SG_DATATYPE_String );
	int Field = pTable->Get_Field_Count()-1;

	for( sLong i=0; i<pTable->Get_Count(); i++ )
	{
		CSG_Table_Record *pRecord = pTable->Get_Record(i);

		CSG_DateTime Time 	= Get_DateTime("TIMEPOINT", pRecord);
		CSG_DateTime Other 	= Get_DateTime("OTHER", 	pRecord);
		CSG_DateTime Begin 	= Get_DateTime("BEGIN", 	pRecord);
		CSG_DateTime End 	= Get_DateTime("END", 		pRecord);
		
		bool Bool = true;
		switch( Operation )
		{
			case  0: Bool = Time.is_EarlierThan			( Other ); 			break;
			case  1: Bool = Time.is_EqualTo				( Other ); 			break;
			case  2: Bool = Time.is_LaterThan			( Other );			break;
			case  3: Bool = Time.is_SameDate			( Other );			break;
			case  4: Bool = Time.is_SameTime			( Other ); 			break;
			case  5: Bool = Time.is_Between				( Begin, End ); 	break;
			case  6: Bool = Time.is_StrictlyBetween		( Begin, End ); 	break;
			case  7: Bool = CSG_DateTime::is_LeapYear	( Time.Get_Year()); break;
			case  8: Bool = Time.is_DST					(); 				break;
		}

		if( Output == 0 )
			pRecord->Set_Value( Field, Bool );
		if( Output == 1 )
			pRecord->Set_Value( Field, Bool ? True : False );
	}
	
	//-----------------------------------------------------
	if( pTable == Parameters("TABLE")->asTable() )
	{
		DataObject_Update(pTable);
	}


	return( true );
}

///////////////////////////////////////////////////////////
//														 //
//														 //
//														 //
///////////////////////////////////////////////////////////
