Format dates w/ PHP syntax (WIP)
Posted: Wed Aug 24, 2011 12:52 am
Here's a useful chunk of code... I have "mostly" mimicked the functionality of PHP's date() formatting function in PureBasic.
Think of it as an expanded version of PB's own FormatDate() command.
For PHP's syntax, see their documentation here: http://php.net/manual/en/function.date.php
EnableExplicit-friendly, cross-platform compileable, comes with a ready-to-run example!
A single procedure, with no global variables or macros to carry with it!
But be aware it is a work in progress!
A few of the format codes have not been implemented yet, and the time zone codes are not implemented on Mac/Linux!
And it is not 100% verified... (for example, some padding lengths might differ from PHP's?)
I am completely open to suggestions, contributions, and improvements!
[/size]
Think of it as an expanded version of PB's own FormatDate() command.
For PHP's syntax, see their documentation here: http://php.net/manual/en/function.date.php
EnableExplicit-friendly, cross-platform compileable, comes with a ready-to-run example!
A single procedure, with no global variables or macros to carry with it!
But be aware it is a work in progress!
A few of the format codes have not been implemented yet, and the time zone codes are not implemented on Mac/Linux!
And it is not 100% verified... (for example, some padding lengths might differ from PHP's?)
I am completely open to suggestions, contributions, and improvements!
Code: Select all
; +---------------+
; | PHPFormatDate |
; +---------------+
; | 8.21.2011 . Creation (PB 4.51)
; | .22. . Added full date/time combos, Swatch time, difference from GMT
; | .23. - Version 1.0 (for PB forums)
; | 5.11.2016 - Version 1.1 (corrected day prefixes such as "st")
; | 1.23.2017 - Version 1.2 (corrected GMT offset bug when passing midnight)
;
;
;
; This procedure mimics the native date() function of the PHP language.
; It can be used as an expanded replacement for PB's FormatDate() function,
; but be aware that it uses completely different syntax!
; The Timestamp argument defaults to -1, which is replaced by the current time.
;
; The format syntax (list of character codes) matches PHP's syntax here:
; *** http://php.net/manual/en/function.date.php ***
;
;
;
; Note the following exceptions, and their contribution to the result:
;
; 'u' (microseconds) PB timestamps do not use microseconds, always becomes "000000"
; 'W' (ISO week number) not implemented, becomes "?"
; 'o' (ISO year) not implemented, becomes "?"
; 'e' (time zone ID) not implemented, becomes "?"
; 'I' (daylight savings flag) not implemented, becomes "?"
; 'T' (time zone abbreviation) not implemented, becomes "?"
;
; Also:
; * Time zones are not yet implemented on Mac/Linux. GMT offset will alway be 00:00.
;
; PHPFormatDate (Version 1.2)
Procedure.s PHPFormatDate(Format.s, Timestamp.i = -1)
Protected Result.s
Protected Year.i, Month.i, Day.i, Hour.i, Minute.i, Second.i
Protected FromGMT.i, GMTHour.s, GMTMinute.s, Temp.i
Protected *C.CHARACTER
; Use current time, by default
If (Timestamp = -1)
Timestamp = Date()
EndIf
; OS-dependent code for getting time zone info (GMT offset)
CompilerIf (#PB_Compiler_OS = #PB_OS_Windows)
Protected GMTTime.SYSTEMTIME, LocalTime.SYSTEMTIME
; Retrieve GMT and local times
GetSystemTime_(GMTTime)
GetLocalTime_(LocalTime)
FromGMT = (LocalTime\wHour - GMTTime\wHour)*60 + (LocalTime\wMinute - GMTTime\wMinute)
If (GMTTime\wDayOfWeek = (LocalTime\wDayOfWeek + 1) % 7)
FromGMT - 24*60
ElseIf (GMTTime\wDayOfWeek = (LocalTime\wDayOfWeek + 7 - 1) % 7)
FromGMT + 24*60
EndIf
; Format time zone offset appropriately
If (FromGMT > 0)
GMTHour = "+" + RSet(Str(FromGMT / 60), 2, "0")
GMTMinute = RSet(Str(FromGMT % 60), 2, "0")
Else
GMTHour = "-" + RSet(Str((0-FromGMT) / 60), 2, "0")
GMTMinute = RSet(Str((0-FromGMT) % 60), 2, "0")
EndIf
CompilerElse
; Mac and Linux GMT code not yet implemented
FromGMT = 0
GMTHour = "+00"
GMTMinute = "00"
CompilerEndIf
; Extract numeric timestamp values
Year = Year (Timestamp)
Month = Month (Timestamp)
Day = Day (Timestamp)
Hour = Hour (Timestamp)
Minute = Minute(Timestamp)
Second = Second(Timestamp)
; Parse through each format character
Result = ""
*C = @Format
While (*C\c)
Select (*C\c)
; Day representations
Case 'd' : Result + RSet(Str(Day), 2, "0")
Case 'D'
Select (DayOfWeek(Timestamp))
Case 0 : Result + "Sun"
Case 1 : Result + "Mon"
Case 2 : Result + "Tue"
Case 3 : Result + "Wed"
Case 4 : Result + "Thu"
Case 5 : Result + "Fri"
Case 6 : Result + "Sat"
EndSelect
Case 'j' : Result + Str(Day)
Case 'l'
Select (DayOfWeek(Timestamp))
Case 0 : Result + "Sunday"
Case 1 : Result + "Monday"
Case 2 : Result + "Tuesday"
Case 3 : Result + "Wednesday"
Case 4 : Result + "Thursday"
Case 5 : Result + "Friday"
Case 6 : Result + "Saturday"
EndSelect
Case 'N' : Result + Str(((DayOfWeek(Timestamp) + 6) % 7) + 1)
Case 'S'
Select (Day)
Case 1, 21, 31 : Result + "st"
Case 2, 22 : Result + "nd"
Case 3, 23 : Result + "rd"
Default : Result + "th"
EndSelect
Case 'w' : Result + Str(DayOfWeek(Timestamp))
Case 'z' : Result + Str(DayOfYear(Timestamp)-1)
; Week representations
Case 'W' : Result + "?" ; ISO week (not implemented)
; Month representations
Case 'F'
Select (Month)
Case 1 : Result + "January"
Case 2 : Result + "February"
Case 3 : Result + "March"
Case 4 : Result + "April"
Case 5 : Result + "May"
Case 6 : Result + "June"
Case 7 : Result + "July"
Case 8 : Result + "August"
Case 9 : Result + "September"
Case 10 : Result + "October"
Case 11 : Result + "November"
Case 12 : Result + "December"
EndSelect
Case 'm' : Result + RSet(Str(Month), 2, "0")
Case 'M'
Select (Month)
Case 1 : Result + "Jan"
Case 2 : Result + "Feb"
Case 3 : Result + "Mar"
Case 4 : Result + "Apr"
Case 5 : Result + "May"
Case 6 : Result + "Jun"
Case 7 : Result + "Jul"
Case 8 : Result + "Aug"
Case 9 : Result + "Sep"
Case 10 : Result + "Oct"
Case 11 : Result + "Nov"
Case 12 : Result + "Dec"
EndSelect
Case 'n' : Result + Str(Month)
Case 't'
Select (Month)
Case 1,3,5,7,8,10,12
Result + "31"
Case 2
If (Year % 400 = 0)
Result + "29"
ElseIf (Year % 100 = 0)
Result + "28"
ElseIf (Year % 4 = 0)
Result + "29"
Else
Result + "28"
EndIf
Case 4,6,9,11
Result + "30"
EndSelect
; Year representations
Case 'L'
If (Year % 400 = 0)
Result + "1"
ElseIf (Year % 100 = 0)
Result + "0"
ElseIf (Year % 4 = 0)
Result + "1"
Else
Result + "0"
EndIf
Case 'o' : Result + "?" ; ISO year (not implemented)
Case 'Y' : Result + Str(Year)
Case 'y' : Result + RSet(Str(Year % 100), 2, "0")
; Time representations
Case 'a'
If (Hour >= 12)
Result + "pm"
Else
Result + "am"
EndIf
Case 'A'
If (Hour >= 12)
Result + "PM"
Else
Result + "AM"
EndIf
Case 'B'
Result + RSet(Str((36000*Hour + 600*Minute + 10*Second) / 864), 3, "0")
Case 'g' : Result + Str(((Hour + 23) % 12) + 1)
Case 'G' : Result + Str(Hour)
Case 'h' : Result + RSet(Str(((Hour + 23) % 12) + 1), 2, "0")
Case 'H' : Result + RSet(Str(Hour), 2, "0")
Case 'i' : Result + RSet(Str(Minute), 2, "0")
Case 's' : Result + RSet(Str(Second), 2, "0")
Case 'u' : Result + "000000" ; microseconds (not implemented)
; Timezone representations
Case 'e' : Result + "?" ; Timezone identifier (not implemented)
Case 'I' : Result + "?" ; Daylight savings flag (not implemented)
Case 'O' : Result + GMTHour + GMTMinute
Case 'P' : Result + GMTHour + ":" + GMTMinute
Case 'T' : Result + "?" ; Timezone abbreviation (not implemented)
Case 'Z' : Result + Str(FromGMT*60)
; Full date/time
Case 'c' : Result + PHPFormatDate("Y-m-d\TH:i:sP")
Case 'r' : Result + PHPFormatDate("D, d M Y H:i:s O", Timestamp)
Case 'U' : Result + RSet(Str(Timestamp), 11, "0")
; Escape or pass all other characters
Case '\' : *C + SizeOf(CHARACTER) : Result + Chr(*C\c)
Default : Result + Chr(*C\c)
EndSelect
*C + SizeOf(CHARACTER)
Wend
ProcedureReturn (Result)
EndProcedure
; =======================================================================================
;- EXAMPLE PROGRAM
; =======================================================================================
CompilerIf (#PB_Compiler_IsMainFile)
;Debug PHPFormatDate("r", Date(2014, 8, 1, 16, 14, 0)) : End
; Create array of all valid codes
#PHPFormats = 38
Dim PHPFormat.s(#PHPFormats - 1)
PHPFormat( 0) = "d"
PHPFormat( 1) = "D"
PHPFormat( 2) = "j"
PHPFormat( 3) = "l"
PHPFormat( 4) = "N"
PHPFormat( 5) = "S"
PHPFormat( 6) = "w"
PHPFormat( 7) = "z"
PHPFormat( 8) = "W"
PHPFormat( 9) = "F"
PHPFormat(10) = "m"
PHPFormat(11) = "M"
PHPFormat(12) = "n"
PHPFormat(13) = "t"
PHPFormat(14) = "L"
PHPFormat(15) = "o"
PHPFormat(16) = "Y"
PHPFormat(17) = "y"
PHPFormat(18) = "a"
PHPFormat(19) = "A"
PHPFormat(20) = "B"
PHPFormat(21) = "g"
PHPFormat(22) = "G"
PHPFormat(23) = "h"
PHPFormat(24) = "H"
PHPFormat(25) = "i"
PHPFormat(26) = "s"
PHPFormat(27) = "u"
PHPFormat(28) = "e"
PHPFormat(29) = "I"
PHPFormat(30) = "O"
PHPFormat(31) = "P"
PHPFormat(32) = "T"
PHPFormat(33) = "Z"
PHPFormat(34) = "c"
PHPFormat(35) = "r"
PHPFormat(36) = "U"
PHPFormat(37) = "\\"
; Create window with ListIcon
OpenWindow(0, 0, 0, 400, 600, "PHPFormatDate Demonstration", #PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_Invisible)
ListIconGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), "Format", 195, #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Result", 195)
SmartWindowRefresh(0,1)
; An example format string
Define Main.s = "\I\t \i\s l \t\h\e jS, \o\f M Y."
AddGadgetItem(0, 0, Main)
; Add all valid formats
Define i.i, Event.i, Timestamp.i
For i = 0 To #PHPFormats - 1
AddGadgetItem(0, i+1, PHPFormat(i))
Next i
; Timer to update
AddWindowTimer(0, 0, 1000)
Repeat
Event = WaitWindowEvent()
; Update all fields
If (Event = #PB_Event_Timer)
Timestamp.i = Date()
SetGadgetItemText(0, 0, PHPFormatDate(Main, Timestamp), 1)
For i = 0 To #PHPFormats - 1
SetGadgetItemText(0, i+1, PHPFormatDate(PHPFormat(i), Timestamp), 1)
Next i
HideWindow(0, 0)
EndIf
Until (Event = #PB_Event_CloseWindow)
CompilerEndIf
; EOF