Prevent exception for empty dates

Prevent exception for empty dates

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//

///
/// Convert a 24-hour military time to a 12-hour clock time.
///
/// <param name="cTime"> A valid military time in the form hh:mm:ss, where hh is hours in 24-hour format, mm is minutes, and ss is seconds.</param>
/// <returns>
/// An 11-character string in 12-hour format with either "am" or "pm."  If cTime does not represent a valid military time, a String.Empty is returned.
/// </returns>
FUNCTION AmPm(cTime AS STRING) AS STRING
	LOCAL nSeconds AS DWORD
	LOCAL nHours AS DWORD
	LOCAL nMinutes AS DWORD
	IF String.IsNullOrEmpty(cTime)
		RETURN ""
	ENDIF
	nSeconds := Secs(cTime)
	IF (nSeconds) > 86400
		RETURN ""
	ENDIF
	nSeconds := nSeconds % 86400
	nHours   := nSeconds / 3600
	nSeconds := nSeconds % 3600
	nMinutes := nSeconds / 60
	nSeconds := nSeconds % 60
	RETURN _TimeString(nHours, nMinutes, nSeconds, TRUE, GetAmExt(), GetPmExt())

///
/// Return the difference between two time strings.
///
/// <param name="cStartTime">The starting time in the form HH:mm:ss.</param>
/// <param name="cEndTime">The ending time in the form HH:mm:ss.</param>
/// <returns>
/// The amount of time that has elapsed from cStartTime to cEndTime as a time string in the format hh:mm:ss.
/// </returns>
/// <remarks>
/// </remarks>
FUNCTION ElapTime(cStartTime AS STRING,cEndTime AS STRING) AS STRING
	LOCAL nStart AS DWORD
	LOCAL nEnd   AS DWORD
	LOCAL nDiff  AS DWORD
	nStart := Secs(cStartTime)
	nEnd   := Secs(cEndTime)
	IF nStart > nEnd
		nDiff := 86400 + nEnd - nStart
	ELSE
		nDiff := nEnd - nStart
	ENDIF
	RETURN TString(nDiff)

///
/// Format a set of numbers representing an hour, minute, and second as a time string.
///
/// <param name="dwHour"></param>
/// <param name="dwMinute"></param>
/// <param name="dwSeconds"></param>
/// <returns>
/// </returns>
FUNCTION ConTime(dwHour AS DWORD,dwMinute AS DWORD,dwSeconds AS DWORD) AS STRING
   RETURN _TimeString( dwHour, dwMinute, dwSeconds, FALSE, "", "" )

///
/// Return the timestring from a DateTime structure
///
/// <param name="dt"></param>
/// <returns>
/// </returns>
FUNCTION ConTime(dt AS DateTime) AS STRING
	RETURN _TimeString((DWORD) dt:Hour,(DWORD) dt:Minute,(DWORD) dt:Second, FALSE, "","")

///
/// Convert the number that identifies a day into the name of the day.
///
/// <param name="dwDay">A number from 1 to 7.</param>
/// <returns>
/// </returns>
FUNCTION NToCDoW(dwDay AS DWORD) AS STRING
	LOCAL result AS STRING
	IF dwDay < 1 .OR. dwDay > 7
		result := ""
	ELSEIF RuntimeState.International == CollationMode.Clipper
		result := __CavoStr(VOErrors.RT_MSG_DAY1 + dwDay -1)
	ELSE
		VAR culture := System.Globalization.CultureInfo.CurrentCulture
		result := culture:DateTimeFormat:GetDayName((DayOfWeek) dwDay-1)
	ENDIF
	RETURN result
///
/// Convert the number that identifies a month into the name of the month.
///
/// <param name="dwMonth"></param>
/// <returns>
/// </returns>
FUNCTION NToCMonth(dwMonth AS DWORD) AS STRING
	LOCAL result AS STRING
	IF dwMonth < 1 .OR. dwMonth > 12
		result := ""
	ELSEIF RuntimeState.International == CollationMode.Clipper
		result := __CavoStr(VOErrors.RT_MSG_MONTH1 + dwMonth -1)
	ELSE
		VAR culture := System.Globalization.CultureInfo.CurrentCulture
		result := culture:DateTimeFormat:GetMonthName((INT)dwMonth)
	ENDIF
	RETURN result

///
/// Return a time as the number of seconds that have elapsed since midnight.
///
/// <param name="cTime">The time to convert to seconds, in the form hh:mm:ss.</param>
/// <returns>The number of seconds from midnight to the time specified.  The return value cannot be greater than 86,400, the number of seconds in a day.
/// </returns>
FUNCTION Secs(cTime AS STRING) AS DWORD
	LOCAL cSeparator AS STRING
	LOCAL nHours AS INT
	LOCAL nMinutes AS INT
	LOCAL nSeconds AS INT
	LOCAL nExpectedLength AS INT
	LOCAL result AS DWORD
	IF String.IsNullOrEmpty(cTime)
		RETURN 0
	ENDIF
	cSeparator := chr(GetTimeSep())
	nExpectedLength := 6 + 2 * cSeparator:Length
	IF cTime:Length >= nExpectedLength
		LOCAL nOffSet := 0 AS INT
		TRY
			nHours   := Int32.Parse(cTime:Substring(nOffSet,2))
			nOffSet += cSeparator:Length +2
			nMinutes := Int32.Parse(cTime:Substring(nOffSet,2))
			nOffSet += cSeparator:Length +2
			nSeconds := Int32.Parse(cTime:Substring(nOffSet,2))
			result := (DWORD) nHours * 3600 + nMinutes * 60 + nSeconds
		CATCH
			result := 0
		END TRY
	ELSE
		result := 0
	ENDIF
	RETURN result

///
/// Convert a specified number of seconds to days.
///
// <param name="nSeconds">The number of seconds to convert to days.</param>
/// <returns>The number of days to the nearest day.</returns>
FUNCTION Days(nSeconds AS REAL8) AS INT
   RETURN (INT) (nSeconds / 84600) // 24*60*60

///
/// Return the number of seconds that have elapsed since midnight.
///
/// <returns>The number of seconds that have elapsed since midnight in the form seconds.hundredths.  Numbers range from 0 to 86,399.</returns>
FUNCTION Seconds() AS REAL8
	VAR dt := DateTime.Now
	RETURN dt:Hour * 3600 + dt:Minute * 60 + dt:Second + Math.Round( (REAL8) dt:Millisecond/1000,2)

///
/// Return the system time in a format determined by various international settings.
///
/// <returns>
/// </returns>
FUNCTION Time() AS STRING
   VAR d := DateTime.Now
   RETURN _TimeString(d)

///
/// Return the system time in 24-hour format.
///
/// <returns>
/// </returns>
FUNCTION Time24() AS STRING
   LOCAL d := DateTime.Now AS DateTime
   RETURN _TimeString((DWORD) d:Hour,(DWORD) d:Minute,(DWORD) d:Second,FALSE,"","")

/// Convert a specified number of seconds to a time string.
FUNCTION TString(fSeconds AS REAL8) AS STRING
   RETURN TString( (DWORD) Math.Round( fSeconds, MidpointRounding.ToEven ) )

/// Convert a specified number of seconds to a time string.
FUNCTION TString(dwSeconds AS DWORD) AS STRING
   LOCAL dwHours AS DWORD
   LOCAL dwMinutes AS DWORD
   // truncate to one day
   dwSeconds := dwSeconds % (24 * 60 * 60)
   dwHours   := dwSeconds / (60 * 60)
   dwSeconds := dwSeconds % (60 * 60)
   dwMinutes := dwSeconds / 60
   dwSeconds := dwSeconds % 60
   RETURN _TimeString(dwHours, dwMinutes, dwSeconds, GetAmPm(), GetAMExt(), GetPMExt())

INTERNAL FUNCTION _TimeString( d AS DateTime ) AS STRING
   RETURN _TimeString( (DWORD) d:Hour, (DWORD) d:Minute, (DWORD) d:Second, SetAMPM(), GetAMExt(), GetPMExt() )

INTERNAL FUNCTION _TimeString( h AS DWORD, m AS DWORD, s AS DWORD, lAMPM AS LOGIC, cAM AS STRING, cPM AS STRING ) AS STRING
   LOCAL cTimeSep   AS STRING
   LOCAL lAfternoon AS LOGIC
   // no exceptions, vo simply returns an empty string
   IF h < 0 || h > 23
      RETURN ""
   ELSEIF m < 0 || m > 59
      RETURN ""
   ELSEIF s < 0 || s > 59
      RETURN ""
   ENDIF

   IF s == 60
      s := 0
      m += 1
      IF m == 60
         m := 0
         h += 1
      ENDIF
      IF h == 24
         h := 0
      ENDIF
   ENDIF

   cTimeSep := Chr( GetTimeSep() )

   lAfternoon := h >= 12

   IF lAMPM
      IF h > 12
         h -= 12
      ELSEIF h == 0
         h := 12
      ENDIF
   ENDIF

   RETURN String.Format( "{0:00}{3}{1:00}{3}{2:00}{4}", h, m, s, cTimeSep, IIF( lAMPM, IIF( lAfternoon, cPM, cAM ), "" ) )

///
/// Format a set of numbers representing a year, month, and day as a Date.
///
/// <param name="dwY">A valid year.  If the century digits are not specified, the century is determined by the rules of SetEpoch(). </param>
/// <param name="dwM">A number from 1 through 12 representing a valid month. </param>
/// <param name="dwDay">A number representing a valid day of dwMonth.</param>
/// <returns>The date that corresponds to the passed arguments.  If any of the arguments specified do not represent a valid year, month, or day, a NULL_DATE is returned.</returns>
FUNCTION _ConDate(dwY AS DWORD,dwM AS DWORD,dwDay AS DWORD) AS DateTime
	IF dwY < 100
		LOCAL lAfter AS LOGIC
		lAfter := dwY > XSharp.RuntimeState.EpochYear
		dwY += XSharp.RuntimeState.EpochCent
		IF lAfter
			dwY -= 100
		ENDIF
	ENDIF
	RETURN DateTime{(INT) dwY,(INT) dwM,(INT) dwDay}

FUNCTION _CToD(cDate AS STRING, cDateFormat AS STRING) AS DateTime
	LOCAL dDate AS DateTime
	LOCAL nDay, nMonth, nYear AS DWORD
	LOCAL nDayPos, nMonthPos, nYearPos AS INT
	dDate := DateTime.MinValue
	IF string.IsNullOrEmpty(cDate) .OR. String.IsNullOrEmpty(cDateFormat) .OR. cDate == RuntimeState.GetValue<STRING>(Set.DateFormatEmpty)
		RETURN dDate
	ENDIF
	LOCAL nPos AS INT
	LOCAL cSep AS STRING
	nDayPos := nMonthPos := nYearPos := -1
	cSep := "./-"
	nPos :=-1
	FOREACH c AS CHAR IN cDateFormat
		SWITCH c
		CASE 'D'
			IF nDayPos == -1
				++nPos
				nDayPos  := nPos
			ENDIF
		CASE 'M'
			IF nMonthPos == -1
				++nPos
				nMonthPos  := nPos
			ENDIF
		CASE 'Y'
			IF nYearPos == -1
				++nPos
				nYearPos  := nPos
			ENDIF
		OTHERWISE
			IF cSep:IndexOf(c) == -1
				cSep += c:ToString()
			ENDIF
		END SWITCH
	NEXT
	IF nDayPos == -1 .OR. nMonthPos == -1 .OR. nYearPos == -1
		RETURN dDate
	ENDIF
	TRY
		// we now know the seperators and the positions in the string
		LOCAL aNums := cDate:Split(cSep:ToCharArray()) AS STRING[]
		IF UInt32.TryParse(aNums[nDayPos], OUT nDay) .AND. ;
    		UInt32.TryParse(aNums[nMonthPos], OUT nMonth) .AND. ;
	    	UInt32.TryParse(aNums[nYearPos], OUT nYear)
		    IF aNums[nYearPos]:Length < 4
			    // Century missing ?
			    dDate := _ConDate(nYear, nMonth, nDay)
		    ELSE
			    dDate := DateTime{(INT)nYear, (INT)nMonth, (INT)nDay}
            ENDIF
        ELSE
            dDate := DateTime.MinValue
        ENDIF
	CATCH
		dDate := DateTime.MinValue
	END TRY
	RETURN dDate

///
/// Convert an ANSI date string to date format.
///
/// <param name="cDate">A string in the ANSI form yyyy.mm.dd, where yy, mm, and dd represent year, month, and day respectively.
/// The year, month, and day can be separated by any character other than a number.
/// cDate is always interpreted as an ANSI string and is not dependent on SetDateFormat() or SetDateCountry().
/// If the century digits are not specified, the century is determined by the rules of SetEpoch().</param>
/// <returns>The date value that corresponds to the numbers specified in <paramref name="cDate"/>.  If cDate is not a valid ANSI date, CToDAnsi() returns a NULL_DATE.
/// </returns>
FUNCTION _CToDAnsi(cDate AS STRING) AS DateTime
	RETURN _CToD(cDate, "YYYY.MM.DD")

///
/// Convert a Date to a string.
///
/// <param name="d">The Date to be converted.</param>
/// <returns>
/// A string representation of the given Date, formatted in the current Date format.
/// </returns>
FUNCTION _DToC(d AS DateTime) AS STRING
	LOCAL result:="" AS STRING
	LOCAL cFormat := XSharp.RuntimeState.GetValue<STRING>(Set.DateFormatNet) AS STRING
	IF d != DateTime.Minvalue
		LOCAL dt := d AS Datetime
		result := d:ToString(cFormat)
	ELSE
		result := RuntimeState.NullDateString
	ENDIF
	RETURN result

///
/// Convert a Date value to a string formatted as string in ANSI format
///
/// <param name="dDate">The Date to be converted</param>
/// <returns>
/// An 8-character string in the format yyyymmdd.  If dDate is a NULL_DATE, a string of eight spaces is returned.  The return value is not affected by the current date format.
/// </returns>
FUNCTION _DToS(dDate AS DateTime) AS STRING
	LOCAL result:="        " AS STRING
	IF dDate != DateTime.MinValue
		result := dDate:ToString("yyyyMMdd")
	ENDIF
	RETURN result

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//

///
/// Convert a 24-hour military time to a 12-hour clock time.
///
/// <param name="cTime"> A valid military time in the form hh:mm:ss, where hh is hours in 24-hour format, mm is minutes, and ss is seconds.</param>
/// <returns>
/// An 11-character string in 12-hour format with either "am" or "pm."  If cTime does not represent a valid military time, a String.Empty is returned.
/// </returns>
FUNCTION AmPm(cTime AS STRING) AS STRING
	LOCAL nSeconds AS DWORD
	LOCAL nHours AS DWORD
	LOCAL nMinutes AS DWORD
	IF String.IsNullOrEmpty(cTime)
		RETURN ""
	ENDIF
	nSeconds := Secs(cTime)
	IF (nSeconds) > 86400
		RETURN ""
	ENDIF
	nSeconds := nSeconds % 86400
	nHours   := nSeconds / 3600
	nSeconds := nSeconds % 3600
	nMinutes := nSeconds / 60
	nSeconds := nSeconds % 60
	RETURN _TimeString(nHours, nMinutes, nSeconds, TRUE, GetAmExt(), GetPmExt())

///
/// Return the difference between two time strings.
///
/// <param name="cStartTime">The starting time in the form HH:mm:ss.</param>
/// <param name="cEndTime">The ending time in the form HH:mm:ss.</param>
/// <returns>
/// The amount of time that has elapsed from cStartTime to cEndTime as a time string in the format hh:mm:ss.
/// </returns>
/// <remarks>
/// </remarks>
FUNCTION ElapTime(cStartTime AS STRING,cEndTime AS STRING) AS STRING
	LOCAL nStart AS DWORD
	LOCAL nEnd   AS DWORD
	LOCAL nDiff  AS DWORD
	nStart := Secs(cStartTime)
	nEnd   := Secs(cEndTime)
	IF nStart > nEnd
		nDiff := 86400 + nEnd - nStart
	ELSE
		nDiff := nEnd - nStart
	ENDIF
	RETURN TString(nDiff)

///
/// Format a set of numbers representing an hour, minute, and second as a time string.
///
/// <param name="dwHour"></param>
/// <param name="dwMinute"></param>
/// <param name="dwSeconds"></param>
/// <returns>
/// </returns>
FUNCTION ConTime(dwHour AS DWORD,dwMinute AS DWORD,dwSeconds AS DWORD) AS STRING
   RETURN _TimeString( dwHour, dwMinute, dwSeconds, FALSE, "", "" )

///
/// Return the timestring from a DateTime structure
///
/// <param name="dt"></param>
/// <returns>
/// </returns>
FUNCTION ConTime(dt AS DateTime) AS STRING
	RETURN _TimeString((DWORD) dt:Hour,(DWORD) dt:Minute,(DWORD) dt:Second, FALSE, "","")

///
/// Convert the number that identifies a day into the name of the day.
///
/// <param name="dwDay">A number from 1 to 7.</param>
/// <returns>
/// </returns>
FUNCTION NToCDoW(dwDay AS DWORD) AS STRING
	LOCAL result AS STRING
	IF dwDay < 1 .OR. dwDay > 7
		result := ""
	ELSEIF RuntimeState.International == CollationMode.Clipper
		result := __CavoStr(VOErrors.RT_MSG_DAY1 + dwDay -1)
	ELSE
		VAR culture := System.Globalization.CultureInfo.CurrentCulture
		result := culture:DateTimeFormat:GetDayName((DayOfWeek) dwDay-1)
	ENDIF
	RETURN result
///
/// Convert the number that identifies a month into the name of the month.
///
/// <param name="dwMonth"></param>
/// <returns>
/// </returns>
FUNCTION NToCMonth(dwMonth AS DWORD) AS STRING
	LOCAL result AS STRING
	IF dwMonth < 1 .OR. dwMonth > 12
		result := ""
	ELSEIF RuntimeState.International == CollationMode.Clipper
		result := __CavoStr(VOErrors.RT_MSG_MONTH1 + dwMonth -1)
	ELSE
		VAR culture := System.Globalization.CultureInfo.CurrentCulture
		result := culture:DateTimeFormat:GetMonthName((INT)dwMonth)
	ENDIF
	RETURN result

///
/// Return a time as the number of seconds that have elapsed since midnight.
///
/// <param name="cTime">The time to convert to seconds, in the form hh:mm:ss.</param>
/// <returns>The number of seconds from midnight to the time specified.  The return value cannot be greater than 86,400, the number of seconds in a day.
/// </returns>
FUNCTION Secs(cTime AS STRING) AS DWORD
	LOCAL cSeparator AS STRING
	LOCAL nHours AS INT
	LOCAL nMinutes AS INT
	LOCAL nSeconds AS INT
	LOCAL nExpectedLength AS INT
	LOCAL result AS DWORD
	IF String.IsNullOrEmpty(cTime)
		RETURN 0
	ENDIF
	cSeparator := chr(GetTimeSep())
	nExpectedLength := 6 + 2 * cSeparator:Length
	IF cTime:Length >= nExpectedLength
		LOCAL nOffSet := 0 AS INT
		TRY
			nHours   := Int32.Parse(cTime:Substring(nOffSet,2))
			nOffSet += cSeparator:Length +2
			nMinutes := Int32.Parse(cTime:Substring(nOffSet,2))
			nOffSet += cSeparator:Length +2
			nSeconds := Int32.Parse(cTime:Substring(nOffSet,2))
			result := (DWORD) nHours * 3600 + nMinutes * 60 + nSeconds
		CATCH
			result := 0
		END TRY
	ELSE
		result := 0
	ENDIF
	RETURN result

///
/// Convert a specified number of seconds to days.
///
// <param name="nSeconds">The number of seconds to convert to days.</param>
/// <returns>The number of days to the nearest day.</returns>
FUNCTION Days(nSeconds AS REAL8) AS INT
   RETURN (INT) (nSeconds / 84600) // 24*60*60

///
/// Return the number of seconds that have elapsed since midnight.
///
/// <returns>The number of seconds that have elapsed since midnight in the form seconds.hundredths.  Numbers range from 0 to 86,399.</returns>
FUNCTION Seconds() AS REAL8
	VAR dt := DateTime.Now
	RETURN dt:Hour * 3600 + dt:Minute * 60 + dt:Second + Math.Round( (REAL8) dt:Millisecond/1000,2)

///
/// Return the system time in a format determined by various international settings.
///
/// <returns>
/// </returns>
FUNCTION Time() AS STRING
   VAR d := DateTime.Now
   RETURN _TimeString(d)

///
/// Return the system time in 24-hour format.
///
/// <returns>
/// </returns>
FUNCTION Time24() AS STRING
   LOCAL d := DateTime.Now AS DateTime
   RETURN _TimeString((DWORD) d:Hour,(DWORD) d:Minute,(DWORD) d:Second,FALSE,"","")

/// Convert a specified number of seconds to a time string.
FUNCTION TString(fSeconds AS REAL8) AS STRING
   RETURN TString( (DWORD) Math.Round( fSeconds, MidpointRounding.ToEven ) )

/// Convert a specified number of seconds to a time string.
FUNCTION TString(dwSeconds AS DWORD) AS STRING
   LOCAL dwHours AS DWORD
   LOCAL dwMinutes AS DWORD
   // truncate to one day
   dwSeconds := dwSeconds % (24 * 60 * 60)
   dwHours   := dwSeconds / (60 * 60)
   dwSeconds := dwSeconds % (60 * 60)
   dwMinutes := dwSeconds / 60
   dwSeconds := dwSeconds % 60
   RETURN _TimeString(dwHours, dwMinutes, dwSeconds, GetAmPm(), GetAMExt(), GetPMExt())

INTERNAL FUNCTION _TimeString( d AS DateTime ) AS STRING
   RETURN _TimeString( (DWORD) d:Hour, (DWORD) d:Minute, (DWORD) d:Second, SetAMPM(), GetAMExt(), GetPMExt() )

INTERNAL FUNCTION _TimeString( h AS DWORD, m AS DWORD, s AS DWORD, lAMPM AS LOGIC, cAM AS STRING, cPM AS STRING ) AS STRING
   LOCAL cTimeSep   AS STRING
   LOCAL lAfternoon AS LOGIC
   // no exceptions, vo simply returns an empty string
   IF h < 0 || h > 23
      RETURN ""
   ELSEIF m < 0 || m > 59
      RETURN ""
   ELSEIF s < 0 || s > 59
      RETURN ""
   ENDIF

   IF s == 60
      s := 0
      m += 1
      IF m == 60
         m := 0
         h += 1
      ENDIF
      IF h == 24
         h := 0
      ENDIF
   ENDIF

   cTimeSep := Chr( GetTimeSep() )

   lAfternoon := h >= 12

   IF lAMPM
      IF h > 12
         h -= 12
      ELSEIF h == 0
         h := 12
      ENDIF
   ENDIF

   RETURN String.Format( "{0:00}{3}{1:00}{3}{2:00}{4}", h, m, s, cTimeSep, IIF( lAMPM, IIF( lAfternoon, cPM, cAM ), "" ) )

///
/// Format a set of numbers representing a year, month, and day as a Date.
///
/// <param name="dwY">A valid year.  If the century digits are not specified, the century is determined by the rules of SetEpoch(). </param>
/// <param name="dwM">A number from 1 through 12 representing a valid month. </param>
/// <param name="dwDay">A number representing a valid day of dwMonth.</param>
/// <returns>The date that corresponds to the passed arguments.  If any of the arguments specified do not represent a valid year, month, or day, a NULL_DATE is returned.</returns>
FUNCTION _ConDate(dwY AS DWORD,dwM AS DWORD,dwDay AS DWORD) AS DateTime
	IF dwY < 100
		LOCAL lAfter AS LOGIC
		lAfter := dwY > XSharp.RuntimeState.EpochYear
		dwY += XSharp.RuntimeState.EpochCent
		IF lAfter
			dwY -= 100
		ENDIF
	ENDIF
	RETURN DateTime{(INT) dwY,(INT) dwM,(INT) dwDay}

FUNCTION _CToD(cDate AS STRING, cDateFormat AS STRING) AS DateTime
	LOCAL dDate AS DateTime
	LOCAL nDay, nMonth, nYear AS DWORD
	LOCAL nDayPos, nMonthPos, nYearPos AS INT
	dDate := DateTime.MinValue
	IF string.IsNullOrEmpty(cDate) .OR. String.IsNullOrEmpty(cDateFormat)
		RETURN dDate
	ENDIF
	LOCAL nPos AS INT
	LOCAL cSep AS STRING
	nDayPos := nMonthPos := nYearPos := -1
	cSep := "./-"
	nPos :=-1
	FOREACH c AS CHAR IN cDateFormat
		SWITCH c
		CASE 'D'
			IF nDayPos == -1
				++nPos
				nDayPos  := nPos
			ENDIF
		CASE 'M'
			IF nMonthPos == -1
				++nPos
				nMonthPos  := nPos
			ENDIF
		CASE 'Y'
			IF nYearPos == -1
				++nPos
				nYearPos  := nPos
			ENDIF
		OTHERWISE
			IF cSep:IndexOf(c) == -1
				cSep += c:ToString()
			ENDIF
		END SWITCH
	NEXT
	IF nDayPos == -1 .OR. nMonthPos == -1 .OR. nYearPos == -1
		RETURN dDate
	ENDIF
	TRY
		// we now know the seperators and the positions in the string
		LOCAL aNums := cDate:Split(cSep:ToCharArray()) AS STRING[]
		nDay   := Uint32.Parse(aNums[nDayPos])
		nMonth := Uint32.Parse(aNums[nMonthPos])
		nYear  := Uint32.Parse(aNums[nYearPos])
		IF aNums[nYearPos]:Length < 4
			// Century missing ?
			dDate := _ConDate(nYear, nMonth, nDay)
		ELSE
			dDate := DateTime{(INT)nYear, (INT)nMonth, (INT)nDay}
		ENDIF
	CATCH
		dDate := DateTime.MinValue
	END TRY
	RETURN dDate

///
/// Convert an ANSI date string to date format.
///
/// <param name="cDate">A string in the ANSI form yyyy.mm.dd, where yy, mm, and dd represent year, month, and day respectively.
/// The year, month, and day can be separated by any character other than a number.
/// cDate is always interpreted as an ANSI string and is not dependent on SetDateFormat() or SetDateCountry().
/// If the century digits are not specified, the century is determined by the rules of SetEpoch().</param>
/// <returns>The date value that corresponds to the numbers specified in <paramref name="cDate"/>.  If cDate is not a valid ANSI date, CToDAnsi() returns a NULL_DATE.
/// </returns>
FUNCTION _CToDAnsi(cDate AS STRING) AS DateTime
	RETURN _CToD(cDate, "YYYY.MM.DD")

///
/// Convert a Date to a string.
///
/// <param name="d">The Date to be converted.</param>
/// <returns>
/// A string representation of the given Date, formatted in the current Date format.
/// </returns>
FUNCTION _DToC(d AS DateTime) AS STRING
	LOCAL result:="" AS STRING
	LOCAL cFormat := XSharp.RuntimeState.GetValue<STRING>(Set.DateFormatNet) AS STRING
	IF d != DateTime.Minvalue
		LOCAL dt := d AS Datetime
		result := d:ToString(cFormat)
	ELSE
		result := RuntimeState.NullDateString
	ENDIF
	RETURN result

///
/// Convert a Date value to a string formatted as string in ANSI format
///
/// <param name="dDate">The Date to be converted</param>
/// <returns>
/// An 8-character string in the format yyyymmdd.  If dDate is a NULL_DATE, a string of eight spaces is returned.  The return value is not affected by the current date format.
/// </returns>
FUNCTION _DToS(dDate AS DateTime) AS STRING
	LOCAL result:="        " AS STRING
	IF dDate != DateTime.MinValue
		result := dDate:ToString("yyyyMMdd")
	ENDIF
	RETURN result


codegen/QtTest: updated

codegen/QtTest: updated

Modified:
codegen/QtTest/QTestEventList.prg

%%
%% Qt4xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 4
%%
%% Copyright (C) 2020 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$project=Qt4xHb
$module=QtTest

$header

#include "hbclass.ch"

$addRequests

$beginClassFrom=

$addMethods

$endClass

$destructor

#pragma BEGINDUMP

$includes

$prototype=QTestEventList ()
$internalConstructor=|new1|

$prototype=QTestEventList ( const QTestEventList & other )
$internalConstructor=|new2|const QTestEventList &

/*
[1]QTestEventList ()
[2]QTestEventList ( const QTestEventList & other )
*/

HB_FUNC_STATIC( QTESTEVENTLIST_NEW )
{
  if( ISNUMPAR(0) )
  {
    QTestEventList_new1();
  }
  else if( ISNUMPAR(1) && ISQTESTEVENTLIST(1) )
  {
    QTestEventList_new2();
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}
$addMethod=new

$deleteMethod

$prototype=void addDelay ( int msecs )
$method=|void|addDelay|int

$prototype=void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

/*
[1]void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
[2]void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
*/

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYCLICK )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}
$addMethod=addKeyClick

$prototype=void addKeyClicks ( const QString & keys, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClicks|const QString &,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

/*
[1]void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
[2]void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
*/

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYPRESS )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}
$addMethod=addKeyPress

$prototype=void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

/*
[1]void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
[2]void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
*/

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYRELEASE )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}
$addMethod=addKeyRelease

$prototype=void addMouseClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseDClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseDClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseMove ( QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseMove|QPoint=QPoint(),int=-1

$prototype=void addMousePress ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMousePress|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseRelease ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseRelease|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void clear ()
$method=|void|clear|

$prototype=void simulate ( QWidget * w )
$method=|void|simulate|QWidget *

$extraMethods

#pragma ENDDUMP

%%
%% Qt4xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 4
%%
%% Copyright (C) 2020 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$project=Qt4xHb
$module=QtTest

$header

#include "hbclass.ch"

$addRequests

$beginClassFrom=

$addMethods

$endClass

$destructor

#pragma BEGINDUMP

$includes

$prototype=QTestEventList ()
$internalConstructor=|new1|

$prototype=QTestEventList ( const QTestEventList & other )
$internalConstructor=|new2|const QTestEventList &

/*
[1]QTestEventList ()
[2]QTestEventList ( const QTestEventList & other )
*/

HB_FUNC_STATIC( QTESTEVENTLIST_NEW )
{
  if( ISNUMPAR(0) )
  {
    QTestEventList_new1();
  }
  else if( ISNUMPAR(1) && ISQTESTEVENTLIST(1) )
  {
    QTestEventList_new2();
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$deleteMethod

$prototype=void addDelay ( int msecs )
$method=|void|addDelay|int

$prototype=void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

/*
[1]void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
[2]void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
*/

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYCLICK )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}
$addMethod=addKeyClick

$prototype=void addKeyClicks ( const QString & keys, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClicks|const QString &,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

/*
[1]void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
[2]void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
*/

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYPRESS )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}
$addMethod=addKeyPress

$prototype=void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

/*
[1]void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
[2]void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
*/

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYRELEASE )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}
$addMethod=addKeyRelease

$prototype=void addMouseClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseDClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseDClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseMove ( QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseMove|QPoint=QPoint(),int=-1

$prototype=void addMousePress ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMousePress|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseRelease ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseRelease|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void clear ()
$method=|void|clear|

$prototype=void simulate ( QWidget * w )
$method=|void|simulate|QWidget *

$extraMethods

#pragma ENDDUMP