//***************************************************************************** //*** GlobDate.pkg *** //*** *** //*** Author: Ben weijers *** //*** Data Access Nederland *** //*** June 2, 1999 *** //*** *** //*** Purpose: *** //*** Defines a global object to handle common date functionality. *** //***************************************************************************** Use Windows Use Dll //*** Global to store the date handler object handle Global_variable Integer ghoDateHandler //*** //*** Defintions and prototypes to call the GetDateFormat Windows API function. //*** #IFDEF C_LOCALE_NOUSEROVERRIDE #ELSE #Replace C_LOCALE_NOUSEROVERRIDE |CI$80000000 // do not use user overrides #ENDIF #Replace C_DATE_SHORTDATE |CI$00000001 // use short date picture #Replace C_DATE_LONGDATE |CI$00000002 // use long date picture #Replace C_DATE_USE_ALT_CALENDAR |CI$00000004 // use alternate calendar (if any) #IFDEF SYSTEMTIME$DEFINED #ELSE #Replace SYSTEMTIME$DEFINED |CI1 Type SYSTEMTIME Field SYSTEMTIME.wYear As Word // Current year Field SYSTEMTIME.wMonth As Word // Current month January=1, February=2 and so on Field SYSTEMTIME.wDayOfWeek As Word // Current day of the week 0=Sunday, 1=Monday and so on Field SYSTEMTIME.wDay As Word // Current day of the month Field SYSTEMTIME.wHour As Word // Current hour Field SYSTEMTIME.wMinute As Word // Current minute Field SYSTEMTIME.wSecond As Word // Current second Field SYSTEMTIME.wMilliseconds As Word // Current millisecond End_type #ENDIF External_function GetDateFormat "GetDateFormatA" kernel32.dll ; dWord Locale ; dWord dwFlags ; Pointer lpDate ; pointer lpFormat ; Pointer lpDateString ; Integer cchdate ; Returns Integer //*** Definitions #Replace C_ORG_DATE_FORMAT -1 Class cGlobalDateHandler Is An dfObject Procedure Construct_Object Forward Send Construct_object Property Integer Private.piOriginalDateFormat End_Procedure // Construct_Object //*** //*** Procedure: SwitchDateFormat //*** Purppose : Switch the date format to a desired format. //*** //*** Parameters: //*** - Integer iNewFormat //*** The desired new format. Legal values are the defined date formats //*** (DF_DATE_MILITARY, DF_DATE_EUROPEAN, DF_DATE_USA) or //*** C_ORG_DATE_FOMAT //*** //*** Logic: //*** When one of the "normal" date formats is passed the current date //*** format is stored in the property Private.piOriginalDateFormat. If //*** the original date format is requested it is returned as stored in //*** the property. //*** //*** This procedure is intended to be used in by messages that need to //*** temporarily change the date format. They should call //*** SwitchDateFormat with the desired format before doing their //*** operation that require the desired format. And with the //*** C_ORG_DATE_FORMAT constant when these operations are finished. //*** Procedure SwitchDateFormat Integer iNewFormat Integer iOrgFormat If (iNewFormat <> C_ORG_DATE_FORMAT) Begin Get_attribute DF_DATE_FORMAT To iOrgFormat Set_attribute DF_DATE_FORMAT To iNewFormat Set Private.piOriginalDateFormat To iOrgFormat End Else Begin Get Private.piOriginalDateFormat To iOrgFormat Set_attribute DF_DATE_FORMAT To iOrgFormat End End_Procedure // SwitchDateFormat //*** //*** Function: LeftDatePart //*** Purpose : Get the left part of a date as a string //*** //*** Parameters: //*** - String sDate //*** The date string to get the left part from. //*** //*** Returns Integer //*** The left part of the date string //*** //*** Logic: //*** Get the left part of a date string by determining the first //*** separator in the string. //*** Function LeftDatePart String sDate Returns Integer Integer iDateSeparator Integer iLeftPart Get_attribute DF_DATE_SEPARATOR To iDateSeparator Move (Left(sDate, (Pos(Character(iDateSeparator), sDate) - 1))) To iLeftPart Function_Return iLeftPart End_Function // LeftDatePart //*** //*** Function: YearFromDate //*** Purpose : Return the year from a given date //*** //*** Parameters: //*** - Date dDate //*** The date to get the year from //*** //*** Returns Integer //*** The year of the given date //*** //*** Logic: //*** We use the ability of DataFlex to switch date format on the fly. We //*** will switch the format to military, thus putting the year in front //*** of a date string. Then we call the LeftDatePart function to get //*** the year from the date. Last we reset the date format back to its //*** original value. //*** Function YearFromDate Date dDate Returns Integer Integer iYear Send SwitchDateFormat DF_DATE_MILITARY Get LeftDatePart dDate To iYear Send SwitchDateFormat C_ORG_DATE_FORMAT Function_Return iYear End_Function // YearFromDate //*** //*** Function: MonthFromDate //*** Purpose : Return the month from a given date //*** //*** Parameters: //*** - Date dDate //*** The date to get the month from //*** //*** Returns Integer //*** The month of the given date //*** //*** Logic: //*** We use the ability of DataFlex to switch date format on the fly. We //*** will switch the format to US, thus putting the month in front //*** of a date string. Then we call the LeftDatePart function to get //*** the month from the date. Last we reset the date format back to its //*** original value. //*** Function MonthFromDate Date dDate Returns Integer Integer iMonth Send SwitchDateFormat DF_DATE_USA Get LeftDatePart dDate To iMonth Send SwitchDateFormat C_ORG_DATE_FORMAT Function_Return iMonth End_Function // MonthFromDate //*** //*** Function: DayFromDate //*** Purpose : Return the day from a given date //*** //*** Parameters: //*** - Date dDate //*** The date to get the day from //*** //*** Returns Integer //*** The day of the given date //*** //*** Logic: //*** We use the ability of DataFlex to switch date format on the fly. We //*** will switch the format to european, thus putting the day in front //*** of a date string. Then we call the LeftDatePart function to get //*** the day from the date. Last we reset the date format back to its //*** original value. //*** Function DayFromDate Date dDate Returns Integer Integer iDay Send SwitchDateFormat DF_DATE_EUROPEAN Get LeftDatePart dDate To iDay Send SwitchDateFormat C_ORG_DATE_FORMAT Function_Return iDay End_Function // DayFromDate //*** //*** Function: WeekdayNumberFromDate //*** Purpose : get the number of the day in the week //*** //*** Parameters: //*** - Date dDate //*** The date to get the weekday number from. Must be a four digit year //*** date! //*** //*** Returns Integer //*** The weekday number 0=Sunday, 1=Monday and so on //*** //*** Logic //*** Function WeekdayNumberFromDate Date dDate Returns Integer Integer iDayNumber Move (Mod((Integer(dDate) - 2), 7)) To iDayNumber Function_Return iDayNumber End_Function // WeekdayNumberFromDate Function DayOfWeek Date dDate Returns Integer Integer iDayNumber Move (Mod((Integer(dDate) - 2), 7)) To iDayNumber If (iDayNumber = 0) Move 7 To iDayNumber Function_Return (iDayNumber-1) End_Function // DayOfWeek //*** //*** Function: ComposeDate //*** Purpose : Compose a date from the passed year, month and day //*** //*** Parameters: //*** - iYear //*** The year of the date //*** - iMOnth //*** The month of the date //*** - iDay //*** The day of the date //*** //*** Returns Date //*** The date composed of the passed arguments. //*** //*** Logic: //*** Swittch date to military, create a date string, convert it to date //*** and return the converted date. Function ComposeDate Integer iYear Integer iMonth Integer iDay Returns Date Date dDate Integer iDateSeparator Send SwitchDateFormat DF_DATE_USA Get_attribute DF_DATE_SEPARATOR To iDateSeparator Move (String(iMonth) + Character(iDateSeparator) + String(iDay) + Character(iDateSeparator) + String(iYear)) To dDate Send SwitchDateFormat C_ORG_DATE_FORMAT Function_Return dDate End_Function // ComposeDate //*** //*** Function: LastMonthdayDate //*** Purpose : Return the date of the last day in a month //*** //*** Parameters: //*** - Integer iYear //*** The year of the month to get the last day from //*** - Integer iMonth //*** The month to get the last day from //*** //*** Returns Date //*** The date that represents the last day of the passed month in the //*** passed year //*** //*** Logic: //*** We use the DataFlex behavior to force illegal dates to a legal //*** value. Suppose we setup an illegal date like February 31 1999. //*** DataFlex will convert it to March 3 1999. //*** //*** We will use this behavior by assembling a "31 date" and //*** decrementing the day until the month is the desired one. //*** Function LastMonthDayDate Integer iYear Integer iMonth Returns Date Date dDate Integer iDay Integer iCurrentMonth Move 31 To iDay Repeat Get ComposeDate iYear iMonth iDay To dDate Get MonthFromDate dDate To iCurrentMonth Decrement iDay Until (iMonth = iCurrentMonth) Function_Return dDate End_Function // LastMonthDayDate //*** //*** Function: IsLeapYear //*** Purpose : Determine if the passed year is a leap year. //*** //*** Parameters: //*** - Integer iYear //*** The year. //*** //*** Returns Integer (Boolean) //*** True if the year is a leap year, false otherwise. //*** //*** Logic: //*** Determine the number of days in February of the pased year. //*** Function IsLeapYear Integer iYear Returns Integer Date dLastDayOfFebruary Integer iDay //*** Create last month day and get its day number Get LastMonthDayDate iYear 2 To dLastDayOfFebruary Get DayFromDate dLastDayOfFebruary To iDay Function_Return (iDay = 29) End_Function // IsLeapYear //*** //*** Function: DateAsString //*** Purpose : Get the passed date as a string //*** //*** Parameters: //*** - Date dDate //*** The date that must be converted to a string //*** - String sFormat //*** The format picture string. Use the following elements to construct //*** a format picture string. If you use spaces to separate the //*** elements in the format string, these spaces will appear in the same //*** location in the output string. The letters must be in uppercase or //*** lowercase as shown in the table (for example, “MM” not “mm”). The //*** "long" and "short" pictures are case insensitive. Characters in the //*** format string that are enclosed in single quotation marks will //*** appear in the same location and unchanged in the output string. //*** //*** Picture Meaning //*** long The long date as defined by the locale settings of the machine. //*** short The short date as defined by the locale settings of the machine. //*** d Day of month as digits with no leading zero for single-digit days. //*** dd Day of month as digits with leading zero for single-digit days. //*** ddd Day of week as a three-letter abbreviation. The function uses the //*** LOCALE_SABBREVDAYNAME value associated with the specified locale. //*** dddd Day of week as its full name. The function uses the LOCALE_SDAYNAME //*** value associated with the specified locale. //*** M Month as digits with no leading zero for single-digit months. //*** MM Month as digits with leading zero for single-digit months. //*** MMM Month as a three-letter abbreviation. The function uses the //*** LOCALE_SABBREVMONTHNAME value associated with the specified locale. //*** MMMM Month as its full name. The function uses the LOCALE_SMONTHNAME //*** value associated with the specified locale. //*** y Year as last two digits, but with no leading zero for years less than 10. //*** yy Year as last two digits, but with leading zero for years less than 10. //*** yyyy Year represented by full four digits. //*** gg Period/era string. The function uses the CAL_SERASTRING value associated //*** with the specified locale. This element is ignored if the date to be formatted //*** does not have an associated era or period string. //*** //*** For example, to get the date string “Wed, Aug 31 94” use the //*** following picture string: “ddd',' MMM dd yy” (assuming UK or US //*** locale settings apply). No errors are returned for a bad format //*** string. The function simply forms the best date string that it can. //*** //*** Any text that should remain in its exact form in the date string //*** should be enclosed within single quotation marks in the date format //*** picture. The single quotation mark may also be used as an escape //*** character to allow the single quotation mark itself to be displayed //*** in the date string. However, the escape sequence must be enclosed //*** within two single quotation marks. For example, to display the date //*** as "May '93", the format string would be: "MMMM ''''yy" The first //*** and last single quotation marks are the enclosing quotation marks. //*** The second and third single quotation marks are the escape sequence //*** to allow the single quotation mark to be displayed before the century. //*** Function DateAsString Date dDate String sFormat Returns String dWord dwFlags String sDate String sSystemTime Integer wYear Integer wMonth Integer wDay Integer iRequiredSize Pointer pDate Pointer pSystemTime Pointer pFormat //*** Determine date settings Get YearFromDate dDate To wYear Get MonthFromDate dDate To wMonth Get DayFromDate dDate To wDay //*** Prepare the SYSTEMTIME structure ZeroType SYSTEMTIME To sSystemTime Put wYear To sSystemTime At SYSTEMTIME.wYear Put wMonth To sSystemTime At SYSTEMTIME.wMonth Put wDay To sSystemTime At SYSTEMTIME.wDay //*** Get the pointers Case Begin Case (Uppercase(sFormat) = "LONG") Move C_DATE_LONGDATE To dwFlags Move 0 To pFormat Case Break Case (Uppercase(sFormat) = "SHORT") Move C_DATE_SHORTDATE To dwFlags Move 0 To pFormat Case Break Case Else Move 0 To dwFlags GetAddress Of sFormat To pFormat Case End GetAddress Of sSystemTime To pSystemTime //*** Determine the size of the string for the date Move (GetDateFormat(0, dwFlags, pSystemTime, pFormat, 0, 0)) To iRequiredSize Move (Repeat(Character(0), iRequiredSize)) To sDate GetAddress Of sDate To pDate Move (GetDateFormat(0, dwFlags, pSystemTime, pFormat, pDate, iRequiredSize)) To iRequiredSize Function_Return sDate End_Function // DateAsString //*** //*** Function: SysdateAsString //*** Purpose : Get the system date as a string //*** //*** Parameters: //*** - String sFormat //*** Determines how the date will be formatted. See DateAsString for //*** detailed explanation. //*** //*** Returns String //*** The system d ate as a stirng formatted acoording to the passed //*** format string. //*** //*** Logic: //*** Simply call the DateAsString function with the system date. //*** Function SysdateAsString String sFormat Returns String Date dToday String sDate //*** Get the systemdate with four digit year! The format string //*** specifies how this is actually displayed. Sysdate4 dToday Get DateAsString dToday sFormat To sDate Function_Return sDate End_Function // SysdateAsString //*** //*** Function: MonthString //*** Purpose : Returns the month as a string //*** //*** Parameters: //*** - Integer iMonth //*** The number oft he month //*** - Integer bShort //*** Indicates if the string must use the short or long notation. //*** True = short, False = long //*** //*** Returns String //*** The string as month //*** //*** Logic: //*** Composes a date in the desired month and calls DateAsString to get //*** the month name. //*** Function MonthString Integer iMonth Integer bShort Returns String Date dMonth String sMonth String sFormat Get ComposeDate 1999 iMonth 1 To dMonth If bShort ; Move "MMM" To sFormat Else ; Move "MMMM" To sFormat Get DateAsString dMonth sFormat To sMonth Function_Return sMonth End_Function // MonthString //*** //*** Function: DayString //*** Purpose : Returns the day as a string //*** //*** Parameters: //*** - Integer iDayNumber //*** The number of the day, 0=Sunday, 1=Monday and so on //*** - Integer bShort //*** Indicates if the string must use the short or long notation. //*** True = short, False = long //*** //*** Returns String //*** The day as string //*** //*** Logic: //*** Composes a date in the desired day and calls DateAsString to get //*** the day name. To create a day date we take June 6 1999 as a start //*** date. This is a sunday. Add the daynumber to 6 and compose a date. //*** Function DayString Integer iDayNumber Integer bShort Returns String Date dDay String sDay String sFormat Get ComposeDate 1999 6 (6 + iDayNUmber) To dDay If bShort ; Move "ddd" To sFormat Else ; Move "dddd" To sFormat Get DateAsString dDay sFormat To sDay Function_Return sDay End_Function // DayString End_Class // cGlobalDateHandler //*** //*** Procedure: CreateGlobalDateHandler //*** Purpose : Create a global date handler object if one does not exist //*** already. //*** // 2003-07-29 ------------------------------------ Start Nils G. Svedmyr #If PKG_Version<|CI9 Procedure CreateGlobalDateHandler For Desktop #ELSE Procedure CreateGlobalDateHandler Desktop #ENDIF // Procedure CreateGlobalDateHandler For dfDesktop // 2003-07-29 ------------------------------------ Stop Nils G. Svedmyr If (Not(ghoDateHandler)) Begin Object oGlobalDateHandler Is A cGlobalDateHandler Move Self To ghoDateHandler End_Object // GlobalDateHandler End End_Procedure // CreateGlobalHandler //*** //*** Ensure we create a global object on DataFlex desktop level. //*** Send CreateGlobalDateHandler Of Desktop