Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Proper Date Conversion Based on Regional Settings 1

Status
Not open for further replies.

Phylum

IS-IT--Management
Aug 16, 2004
36
US
I periodically run into an issue where the date [format] I'm using in my VBScripts (typically MM/DD/YYYY) don't behave as expected on various machines. Upon further inspection it has to do with the local regional settings on said machine.

What's the best method for ensuring that my dates are always interpreted/converted properly?
How can I make sure #11/2/2012# is treated as November 2, 2012 and not February 11, 2012?
Am I to create something from scratch that evaluates the regional settings on the machine then take action based on that?


For instance, our counterparts across the pond use the DD/MM/YYYY format while most in the US tend to use MM/DD/YYYY. A few people in various US offices not only use the same format as those across the pond, but they also use a different date separators: hyphen (-) or period (.) vs. slash (/). The combinations are endless!

I tried my hand at creating some functions but they don't always work, because someone is using some unexpected format. Can the community help me not only improve this code but also think through this problem situation?

Code:
Function DeployDate(targetDate1, targetTime1)

	Dim targetDate, targetTime, SerializedDate, SerializedTime, SerializedDT
	targetDate = targetDate1
	targetTime = targetTime1

	' Revisit: How to handle other separators?
	' Is this even sound judgement/logic?
	' Some people use periods (.) as separators when entering the date
	If (IsInString(".",targetDate)) Then
		targetDate = Split(targetDate,".")
	End If

	' Some people use slashes (/) as separators when entering the date
	If (IsInString("/",targetDate)) Then
		targetDate = Split(targetDate,"/")
	End If

	' Some people use hyphens (-) as separators when entering the date
	If (IsInString("-",targetDate)) Then
		targetDate = Split(targetDate,"-")
	End If

	' Lets see what we're working with here...
	wscript.echo "Function DeployDate: targetDate(0) is " & targetDate(0)
	wscript.echo "Function DeployDate: targetDate(1) is " & targetDate(1)
	wscript.echo "Function DeployDate: targetDate(2) is " & targetDate(2)


	Select Case Office
		' Revisit: Wowzers - making some huge assumptions here: EU users use a Year Month Day format.
		' Revisit: What about our folks in the US that use this format?
		Case "Europe"
			SerializedDate = DateSerial(targetDate(2),targetDate(1),targetDate(0))
			If (Now() > SerializedDate) Then
				wscript.echo "Function DeployDate: Now(" & Now() & ") is > SerializedDate(" & SerializedDate &")"
			Else
				wscript.echo "Function DeployDate: Now(" & Now() & ") is !> SerializedDate(" & SerializedDate &")"
			End If
		' Revisit: Another massive assumption here: US users use the 'normal' Day Month Year format.
		' Revisit: What about those in the US that don't use this format?
		Case Else
			SerializedDate = DateSerial(targetDate(2),targetDate(0),targetDate(1))
			If (Now() > SerializedDate) Then
				wscript.echo "Function DeployDate: Now(" & Now() & ") is > SerializedDate(" & SerializedDate &")"
			Else
				wscript.echo "Function DeployDate: Now(" & Now() & ") is !> SerializedDate(" & SerializedDate &")"
			End If
	End Select

	' If a time wasn't specified we'll just default to 1AM
	' Time format rarely matters (read: i've never run into an incorrect time issue)
	If (Len(targetTime) = 8) Then
		targetTime = Split(targetTime,":")
		SerializedTime = TimeSerial(targetTime(0),targetTime(1),targetTime(2))
		wscript.echo "Function DeployDate: SerializedTime is " & SerializedTime
	Else
		SerializedTime = TimeSerial(01,00,00)
		wscript.echo "Function DeployDate: SerializedTime is " & SerializedTime
	End If

	SerializedDT = SerializedDate & " " & SerializedTime
	wscript.echo "Function DeployDate: SerializedDT is " & SerializedDT
	wscript.echo "Function DeployDate: CDate(SerializedDT) is " & CDate(SerializedDT)

	If (Now() > CDate(SerializedDT)) Then
		wscript.echo "Now() is > CDate(SerializedDT)"
	Else
		wscript.echo "Now() is !> CDate(SerializedDT)"
	End If

	On Error GoTo 0
	DeployDate = CDate(SerializedDT)
End Function

Have I over complicated the situation?

HELP!!
Sincerely - Going bonkers! :)
 
So I spent some time trying to figure out Locales, Regional Settings etc and decided on using just the LocalDateTime property in Win32_OperatingSystem:

Code:
Function CurDT
	Dim s_oWMIService, s_colItems, s_oItem
	Dim s_sLocalDateTime, s_iLocalMonth, s_iLocalDay, s_iLocalYear
	Dim s_iLocalHour, s_iLocalMinute, s_iLocalSecond
	Dim s_MMDDYYYY, s_YYYYDDMM, S_DDMMYYYY, s_HHMMSS
	Dim s_CurDT

	Set s_oWMIService = GetObject("winmgmts:\\.\root\cimv2")    
    Set s_colItems = s_oWMIService.ExecQuery("Select * from Win32_OperatingSystem",,48)

    For Each s_oItem in s_colItems
        s_sLocalDateTime = s_oItem.LocalDateTime
        s_iLocalMonth = Mid(s_oItem.LocalDateTime,5,2)
        s_iLocalDay = Mid(s_oItem.LocalDateTime,7,2)
        s_iLocalYear = Left(s_oItem.LocalDateTime,4)
        s_iLocalHour = Mid(s_oItem.LocalDateTime,9,2)
        s_iLocalMinute = Mid(s_oItem.LocalDateTime,11,2)
        s_iLocalSecond = Mid(s_oItem.LocalDateTime,13,2)
    Next

	'debuglog "Month: " & s_iLocalMonth
	'debuglog "Day: " & s_iLocalDay
	'debuglog "Year: " & s_iLocalYear
	'debuglog "Hour: " & s_iLocalHour
	'debuglog "Minute: " & s_iLocalMinute
	'debuglog "Second: " & s_iLocalSecond

	s_MMDDYYYY = s_iLocalMonth & "/" & s_iLocalDay & "/" & s_iLocalYear
	'debuglog "MMDDYYYY: " & s_MMDDYYYY

	s_HHMMSS = s_iLocalHour & ":" & s_iLocalMinute & ":" & s_iLocalSecond
	'debuglog "HHMMSS: " & s_HHMMSS
	
	s_CurDT = CDate(s_MMDDYYYY & " " & s_HHMMSS)
	'debuglog = "s_CurDT: " & s_CurDT

	CurDT = s_CurDT
End Function

But then I realized two things:
[ol 1]
[li]The way I was setting the date was $datevar = CDate(#11/2/2012#) which would correctly convert it to a date, but to a date using the formatting on the local machine. So if I just used $datevar = "11/2/2012" all was well.[/li]
[li]I could do something like this:
Code:
Function getnow()
	getnow = month(now()) & "/" & day(now()) & "/" & year(now()) & " " & time()
End Function
[/li]
[/ol]
 
Too soon for a bump or is that the solution, to use something like that curdt function?
 
You're correct - I missed a step when I was posting that - the CurDT one looks like the way to go.

Code:
Function CurDT
	Dim s_oWMIService, s_colItems, s_oItem
	Dim s_sLocalDateTime, s_iLocalMonth, s_iLocalDay, s_iLocalYear
	Dim s_iLocalHour, s_iLocalMinute, s_iLocalSecond
	Dim s_MMDDYYYY, s_YYYYDDMM, S_DDMMYYYY, s_HHMMSS
	Dim s_CurDT

	Set s_oWMIService = GetObject("winmgmts:\\.\root\cimv2")    
    Set s_colItems = s_oWMIService.ExecQuery("Select * from Win32_OperatingSystem",,48)

    For Each s_oItem in s_colItems
        s_sLocalDateTime = s_oItem.LocalDateTime
        s_iLocalMonth = Mid(s_oItem.LocalDateTime,5,2)
        s_iLocalDay = Mid(s_oItem.LocalDateTime,7,2)
        s_iLocalYear = Left(s_oItem.LocalDateTime,4)
        s_iLocalHour = Mid(s_oItem.LocalDateTime,9,2)
        s_iLocalMinute = Mid(s_oItem.LocalDateTime,11,2)
        s_iLocalSecond = Mid(s_oItem.LocalDateTime,13,2)
    Next

	timingdebug "Month: " & s_iLocalMonth
	timingdebug "Day: " & s_iLocalDay
	timingdebug "Year: " & s_iLocalYear
	timingdebug "Hour: " & s_iLocalHour
	timingdebug "Minute: " & s_iLocalMinute
	timingdebug "Second: " & s_iLocalSecond

	s_MMDDYYYY = s_iLocalMonth & "/" & s_iLocalDay & "/" & s_iLocalYear
	timingdebug "MMDDYYYY: " & s_MMDDYYYY

	s_HHMMSS = s_iLocalHour & ":" & s_iLocalMinute & ":" & s_iLocalSecond
	timingdebug "HHMMSS: " & s_HHMMSS
	
	s_CurDT = CDate(s_MMDDYYYY & " " & s_HHMMSS)
	timingdebug "s_CurDT: " & s_CurDT

	CurDT = s_CurDT
End Function

Function CurDT_Date
	Dim s_oWMIService, s_colItems, s_oItem
	Dim s_sLocalDateTime, s_iLocalMonth, s_iLocalDay, s_iLocalYear
	Dim s_iLocalHour, s_iLocalMinute, s_iLocalSecond
	Dim s_MMDDYYYY, s_YYYYDDMM, S_DDMMYYYY, s_HHMMSS
	Dim s_CurDT

	Set s_oWMIService = GetObject("winmgmts:\\.\root\cimv2")    
    Set s_colItems = s_oWMIService.ExecQuery("Select * from Win32_OperatingSystem",,48)

    For Each s_oItem in s_colItems
        s_sLocalDateTime = s_oItem.LocalDateTime
        s_iLocalMonth = Mid(s_oItem.LocalDateTime,5,2)
        s_iLocalDay = Mid(s_oItem.LocalDateTime,7,2)
        s_iLocalYear = Left(s_oItem.LocalDateTime,4)
    Next

	timingdebug "Month: " & s_iLocalMonth
	timingdebug "Day: " & s_iLocalDay
	timingdebug "Year: " & s_iLocalYear

	s_MMDDYYYY = s_iLocalMonth & "/" & s_iLocalDay & "/" & s_iLocalYear
	timingdebug "MMDDYYYY: " & s_MMDDYYYY
	
	CurDT_Date = s_MMDDYYYY
End Function

Function CurDT_Time
	Dim s_oWMIService, s_colItems, s_oItem
	Dim s_sLocalDateTime, s_iLocalMonth, s_iLocalDay, s_iLocalYear
	Dim s_iLocalHour, s_iLocalMinute, s_iLocalSecond
	Dim s_MMDDYYYY, s_YYYYDDMM, S_DDMMYYYY, s_HHMMSS
	Dim s_CurDT

	Set s_oWMIService = GetObject("winmgmts:\\.\root\cimv2")    
    Set s_colItems = s_oWMIService.ExecQuery("Select * from Win32_OperatingSystem",,48)

    For Each s_oItem in s_colItems
        s_sLocalDateTime = s_oItem.LocalDateTime
        s_iLocalHour = Mid(s_oItem.LocalDateTime,9,2)
        s_iLocalMinute = Mid(s_oItem.LocalDateTime,11,2)
        s_iLocalSecond = Mid(s_oItem.LocalDateTime,13,2)
    Next

	timingdebug "Hour: " & s_iLocalHour
	timingdebug "Minute: " & s_iLocalMinute
	timingdebug "Second: " & s_iLocalSecond

	s_HHMMSS = s_iLocalHour & ":" & s_iLocalMinute & ":" & s_iLocalSecond
	timingdebug "HHMMSS: " & s_HHMMSS
	
	CurDT_Time = s_HHMMSS
End Function
 
Or you could implement my vbsFormat function from thread329-1570966 and then you can dump CurDT_Date and CurDT_Time, and rewrite CurDT as:

Code:
[blue]Function CurDT()
    CurDT = vbsFormat(Now, "g")
End Function[/blue]

There is a list of the standard date and time formats the function can use are here:
 
strongm - thanks for the reply & link. This is an excellent function indeed.

But something isnt' behaving properly. For future ['scheduled'] deployments, I usually do something like:
Code:
'if (Today's Date is > Target Date) Then
if (Now() > "2/13/2013") Then
     do whatever
end if
That tends to work in most situations, but not for our friends in Europe or those in the US that use a format other than MMM-DD-YYYY (e.g.: YYYY-MMM-DD or DD-MMM-YYYY).

Maybe I've got the logic or the formatting wrong, but its not evaluating the dates correctly:
[ul]
[li]Using 1/13/2013 returns yes - OK[/li]
[li]Using 3/13/2013 returns no - OK[/li]
[li]Using 2/13/2013 returns yes - ??[/li]
[/ul]
Code:
'Dim targetdate: targetdate = vbsFormat("2/13/2013","g")
Dim targetdate: targetdate = vbsFormat("2/13/2013","d")

If (CurDT3 > targetdate) Then
	MsgBox "yes"
Else
	MsgBox "no"
End If

Function CurDT()
    'CurDT = vbsFormat(Now, "g")
    CurDT = vbsFormat(Now, "d")
End Function 

Public Function vbsFormat(Expression, Format)
    vbsFormat = CoreFormat("{0:" & Format & "}", Expression)
End Function

' Allows more of the .NET formatting functionality to be used directly if required
Public Function CoreFormat(Format, Expression)
    CoreFormat = Expression
    On Error Resume Next
    With CreateObject("System.Text.StringBuilder")
        .AppendFormat Format, Expression
        If Err=0 Then CoreFormat = .toString
    End With
End Function
 
>Maybe I've got the logic or the formatting wrong

1) You are not passing an unambiguous date. Your original question was "How can I make sure #11/2/2012# is treated as November 2, 2012", so:

2) If you just want to compare dates I'd use Date rather than Now (some users might have configured their local date

2) You get the dates back as strings, and you are thus doing string comparisons. In some local date/time formats that will give the wrong result when doing comparisons, so for those situations you should specify the sortable date format:

If (vbsFormat(Now, "s") > vbsFormat(#2/13/2013#, "s")) Then

(And finally I'd be tempted to use Date() instead of Now() to get the current date)


 
Sorry if I seem dense - I just wan't getting it. I now have a better understanding of what I was doing wrong.
Thanks again strongm and Geates!
 
Glad you understood my most recent post! :) I was still editing it when I posted, and it really doesn't quite read as I wanted, which would have been:


>Maybe I've got the logic or the formatting wrong

1) You are not passing an unambiguous date. Your original question was "How can I make sure #11/2/2012# is treated as November 2, 2012", so:

[tt]If CurDT > vbsFormat(#2/13/2013#, "d")) Then[/tt]

2) You get the dates back as strings, and you are thus doing string comparisons. In some local date/time formats that will give the wrong result when doing comparisons, so for those situations you should specify the sortable date format:

[tt]If (vbsFormat(Now, "s") > vbsFormat(#2/13/2013#, "s")) Then[/tt]

And finally I'd be tempted to use Date() instead of Now() to get the current date, so:

[tt]If (vbsFormat(Date, "s") > vbsFormat(#2/13/2013#, "s")) Then[/tt]

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top