Page 1 of 2

Advanced FormatDate()

Posted: Tue Jan 16, 2007 1:14 am
by va!n
Would be nice to have following options too... (for example 02 = February)

Code: Select all

%mm     ; Returns "02"
%mmm    ; Returns "Feb"
%mmmm   ; Returns "February"

Posted: Tue Jan 16, 2007 1:33 am
by Flype
agree. and localized of course.

Posted: Tue Jan 16, 2007 1:42 am
by Flype
a handy solution (no api but not localized) :

Code: Select all

removed

Posted: Tue Jan 16, 2007 2:48 am
by va!n
@Flype:
cool! very nice! :)

Posted: Tue Jan 16, 2007 1:41 pm
by Flype
yeah it is !

but here is a more complete one (localized) :

Code: Select all

removed
and by the way GetCalendarInfo_() isn't defined in PB4
even if the associated constants (#CAL_) are defined. :roll:

Posted: Tue Jan 16, 2007 1:48 pm
by gnozal
Flype wrote:and by the way GetCalendarInfo_() isn't defined in PB4
even if the associated constants (#CAL_) are defined. :roll:
And no GetCalendarInfo() function in Windows NT4 or 95 kernel32.dll.
It's for 98/ME and 2k/XP only.

Posted: Tue Jan 16, 2007 2:01 pm
by Flype
yes i know but it should be enough for most people !

MSDN say 'Included in Windows 98 and later.'

Posted: Tue Jan 16, 2007 2:16 pm
by Flype
well,


1/ Here is a short and handy cross-platform solution (but not localized) :

Code: Select all

Macro FormatDate2(mask, date)
FormatDate(ReplaceString(ReplaceString(mask,"%ddd",StringField("Sun,Mon,Tue,Wed,Thu,Fri,Sat",DayOfWeek(date)+1,",")),"%mmm",StringField("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",Month(date),",")),date)
EndMacro

Debug FormatDate2("%dd.%mm.%yyyy %hh:%ii:%ss", Date())
Debug FormatDate2("%ddd %dd %mmm %yyyy %hh:%ii:%ss", Date())

2/ Even if i don't care about Win95 nor NT4, here is a compatible one :

Code: Select all

Procedure.s GetDateFormat(mask.s, date.l)
  Protected st.SYSTEMTIME, result.s = Space(64)
  st\wDay   = Day  (date)
  st\wMonth = Month(date)
  st\wYear  = Year (date)
  If GetDateFormat_(#LOCALE_USER_DEFAULT, 0, @st, mask, @result, 64) 
    ProcedureReturn UCase(Left(result, 1)) + Right(result, Len(result) - 1)
  EndIf
EndProcedure

Procedure.s FormatDate2(mask.s, date.l)
  mask = ReplaceString(mask, "%dddd", GetDateFormat("dddd", date))
  mask = ReplaceString(mask, "%ddd",  GetDateFormat("ddd",  date))
  mask = ReplaceString(mask, "%mmmm", GetDateFormat("MMMM", date))
  mask = ReplaceString(mask, "%mmm",  GetDateFormat("MMM",  date))
  ProcedureReturn FormatDate(mask, date)
EndProcedure

Debug FormatDate2("%ddd %dd %mmm %yyyy  %hh:%ii:%ss", Date())
Debug FormatDate2("%dddd %dd %mmmm %yyyy  %hh:%ii:%ss", Date())

3/ And another localized function for Windows 98 and later :

Code: Select all

Import "kernel32.lib"
  GetCalendarInfoA(lcID.l, calID.l, calType.l, *lpCalData, cchData.l, *lpValue)
EndImport

Procedure.s GetCalendarInfo(type.l)
  Protected result.s = Space(64)
  If GetCalendarInfoA(#LOCALE_USER_DEFAULT, #CAL_GREGORIAN, type, @result, 64, 0)
    ProcedureReturn UCase(Left(result, 1)) + Right(result, Len(result) - 1)
  EndIf
EndProcedure

Procedure.s FormatDate2(mask.s, date.l)
  mask = ReplaceString(mask, "%dddd", GetCalendarInfo(#CAL_SDAYNAME1         + DayOfWeek(date) - 1))
  mask = ReplaceString(mask, "%mmmm", GetCalendarInfo(#CAL_SMONTHNAME1       + Month(date)     - 1))
  mask = ReplaceString(mask, "%ddd",  GetCalendarInfo(#CAL_SABBREVDAYNAME1   + DayOfWeek(date) - 1))
  mask = ReplaceString(mask, "%mmm",  GetCalendarInfo(#CAL_SABBREVMONTHNAME1 + Month(date)     - 1))
  ProcedureReturn FormatDate(mask, date)
EndProcedure

Debug FormatDate2("%ddd %dd %mmm %yyyy  %hh:%ii:%ss", Date())
Debug FormatDate2("%dddd %dd %mmmm %yyyy  %hh:%ii:%ss", Date())

Posted: Tue Jan 16, 2007 2:19 pm
by Derek
Flype wrote:
even if i don't care about Win95 nor NT4, here is a compatible one :
Does anyone even use '95 anymore?

Anyway, good routine, thanks.

Posted: Tue Jan 16, 2007 2:20 pm
by gnozal
Flype wrote:even if i don't care about Win95 nor NT4
:D
Flype wrote:here is a compatible one
Thanks

Re: Advanced FormatDate()

Posted: Tue Jan 16, 2007 2:23 pm
by AND51
va!n wrote:Would be nice to have following options too... (for example 02 = February)

Code: Select all

%mm     ; Returns "02"
%mmm    ; Returns "Feb"
%mmmm   ; Returns "February"
This would be to much work, because I want to have "Montag" and not "Monday". My birhtday is in "Oktober" and not in "October".

I mean: you cannot realize an advanced FormatDate() for all languages.
And if there is no german FormatDate, the germans
1) get angry/jealous
2) cannot use english Dates, because it's not useful for them
This does not only affect on the germans, but also n the french, spain, etc...

Solution: The best was to read the system configuration and try to find the day-names. Hover your clock in the systray and you'll see the day-name in you language; this name must be read to have a user-definded weekday (and everybody will be happy, even the germans). :wink:

Posted: Tue Jan 16, 2007 2:36 pm
by Flype
just a question !

i can see that localized date strings (Win32 API) are all lower case !

in french we usually writes days and months with a first char capitalized :

not 'january' but 'January'.

does it depends of the country ?


well, in the two functions i provided i use this trick :

>> ProcedureReturn UCase(Left(result, 1)) + Right(result, Len(result) - 1)

but you can remove it if needed.

:?:

Re: Advanced FormatDate()

Posted: Wed Jan 17, 2007 7:45 pm
by Shardik
AND51 wrote:
va!n wrote:Would be nice to have following options too... (for example 02 = February)

Code: Select all

%mm     ; Returns "02"
%mmm    ; Returns "Feb"
%mmmm   ; Returns "February"
This would be to much work, because I want to have "Montag" and not "Monday". My birhtday is in "Oktober" and not in "October".

I mean: you cannot realize an advanced FormatDate() for all languages.
And if there is no german FormatDate, the germans
1) get angry/jealous
2) cannot use english Dates, because it's not useful for them
This does not only affect on the germans, but also n the french, spain, etc...

Solution: The best was to read the system configuration and try to find the day-names. Hover your clock in the systray and you'll see the day-name in you language; this name must be read to have a user-definded weekday (and everybody will be happy, even the germans). :wink:
Here is a solution to read the month and day names (long and abbreviated) in the language defined in your OS (tested with Win98SE):

Code: Select all

Procedure.S GetLocaleSetting(SettingID.L)
  Protected Buffer.S
  Protected BufferSize.L
  Protected ErrorMsg.S
  Protected NumBytes.L

  BufferSize = GetLocaleInfo_(#LOCALE_USER_DEFAULT, SettingID, @Buffer, 0)

  Buffer = Space(BufferSize)

  NumBytes = GetLocaleInfo_(#LOCALE_USER_DEFAULT, SettingID, @Buffer, BufferSize)

  If NumBytes = 0
    Select GetLastError_()
      Case #ERROR_INSUFFICIENT_BUFFER
        ErrorMsg = "Insufficient buffer size!"
      Case #ERROR_INVALID_FLAGS
        ErrorMsg = "Invalid flags!"
      Case #ERROR_INVALID_PARAMETER
        ErrorMsg = "Invalid Parameter!"
      Default
        ErrorMsg = "GetLastError() returned undefined error code!"
    EndSelect

    MessageRequester("Error", ErrorMsg, #MB_ICONERROR)

    ProcedureReturn ""
  EndIf

  ProcedureReturn Buffer
EndProcedure


i.L
Setting.S

; ----- Long month names

Debug "Long month names:"

For i = #LOCALE_SMONTHNAME1 To #LOCALE_SMONTHNAME12
  Setting = GetLocaleSetting(i)

  If Setting <> ""
    Debug Setting
  Else
    End
  EndIf
Next i

Debug "-----"
Debug "Abbreviated month names:"

For i = #LOCALE_SABBREVMONTHNAME1	 To #LOCALE_SABBREVMONTHNAME12
  Setting = GetLocaleSetting(i)

  If Setting <> ""
    Debug Setting
  Else
    End
  EndIf
Next i

Debug "-----"
Debug "Long day names:"

For i = #LOCALE_SDAYNAME1 To #LOCALE_SDAYNAME7
  Setting = GetLocaleSetting(i)

  If Setting <> ""
    Debug Setting
  Else
    End
  EndIf
Next i

Debug "-----"
Debug "Abbreviated day names:"

For i = #LOCALE_SABBREVDAYNAME1 To #LOCALE_SABBREVDAYNAME7
  Setting = GetLocaleSetting(i)

  If Setting <> ""
    Debug Setting
  Else
    End
  EndIf
Next i

Posted: Wed Jan 17, 2007 10:16 pm
by Flype
ah yes, thank you - this one is Win95/NT3.1 compatible.

so here is the FormatDate2 :

Code: Select all

Procedure.s GetLocaleInfo(type.l)
  Protected result.s = Space(GetLocaleInfo_(#LOCALE_USER_DEFAULT, type, 0, 0))
  If GetLocaleInfo_(#LOCALE_USER_DEFAULT, type, @result, Len(result))
    ProcedureReturn UCase(Left(result, 1)) + Right(result, Len(result) - 1)
  EndIf
EndProcedure

Procedure.s FormatDate2(mask.s, date.l)
  mask = ReplaceString(mask, "%dddd", GetLocaleInfo(#LOCALE_SDAYNAME1         + DayOfWeek(date) - 1))
  mask = ReplaceString(mask, "%mmmm", GetLocaleInfo(#LOCALE_SMONTHNAME1       + Month(date)     - 1))
  mask = ReplaceString(mask, "%ddd",  GetLocaleInfo(#LOCALE_SABBREVDAYNAME1   + DayOfWeek(date) - 1))
  mask = ReplaceString(mask, "%mmm",  GetLocaleInfo(#LOCALE_SABBREVMONTHNAME1 + Month(date)     - 1))
  ProcedureReturn FormatDate(mask, date)
EndProcedure

Debug FormatDate2("%ddd %dd %mmm %yyyy  %hh:%ii:%ss", Date())
Debug FormatDate2("%dddd %dd %mmmm %yyyy  %hh:%ii:%ss", Date()) 

Posted: Thu Jan 18, 2007 8:23 am
by Shardik
@Flype

You don't need to set the first character to uppercase

Code: Select all

ProcedureReturn UCase(Left(result, 1)) + Right(result, Len(result) - 1)
A simple

Code: Select all

ProcedureReturn result
is sufficient because the day and month names are already returned correctly in upper/lowercase from the Win API call...