Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / Win API / December 2006



Tip: Looking for answers? Try searching our database.

Detemining Whether A Date Is In Daylight Time

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Chip Pearson - 22 Dec 2006 03:00 GMT
I need to write a function that will return True or False indicating whether
a specified date is in the Daylight Savings Time period for that year. The
year of the date may or may not be the current year.  I thought that the
GetTimeZoneInformation API would be of use to test a date. However, I can't
get it to work as I thought it works. Perhaps I'm just dense or perhaps
GetTimeZoneInformation doesn't do what I thought it did.   The Help isn't
quite clear enough,

I have code like the following:

Private Type SYSTEMTIME
       wYear As Integer
       wMonth As Integer
       wDayOfWeek As Integer
       wDay As Integer
       wHour As Integer
       wMinute As Integer
       wSecond As Integer
       wMilliseconds As Integer
End Type

Private Type TIME_ZONE_INFORMATION
       Bias As Long
       StandardName(0 To 31) As Integer
       StandardDate As SYSTEMTIME
       StandardBias As Long
       DaylightName(0 To 31) As Integer
       DaylightDate As SYSTEMTIME
       DaylightBias As Long
End Type

Private Declare Function GetTimeZoneInformation Lib "kernel32" ( _
   lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long

Private Const TIME_ZONE_ID_UNKNOWN = 0
Private Const TIME_ZONE_ID_STANDARD = 1
Private Const TIME_ZONE_ID_DAYLIGHT = 2
Private Const TIME_ZONE_ID_INVALID = -1

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function IsDateInDST(DateVal As Long) As Boolean

TZI.DaylightDate.wYear = 0
TZI.DaylightDate.wMonth = 4     ' April
TZI.DaylightDate.wDayOfWeek = 0 ' Sunday
TZI.DaylightDate.wDay = 1       ' First Sunday

TZI.StandardDate.wYear = 0
TZI.StandardDate.wMonth = 11    ' November
TZI.StandardDate.wDayOfWeek = 0 ' Sunday
TZI.StandardDate.wDay = 1       ' First Sunday

Res = GetTimeZoneInformation(TZI)

DSTStart = DateSerial(Year(DateVal), TZI.DaylightDate.wMonth,
TZI.DaylightDate.wDay)
DSTEnd = DateSerial(Year(DateVal), TZI.StandardDate.wMonth,
TZI.StandardDate.wDay)

If (CLng(DateVal) >= DSTStart) And (CLng(DateVal) <= DSTEnd) Then
   IsDateInDST = True
Else
   IsDateInDST = False
End If

End Function
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

This clearly doesn't work The help isn't very clear, but it was my
understanding that if I set the values of TZI.DaylightDate to the value as
shown above, GetTimeZoneInformation would populate the TZI.DaylightDate and
TZI.StandardDate with the dates of the start of Daylight and Standard times.

I guess my real question is how do I determine the start and end dates of
the Daylight Saving Period and the start and end dates of the Standard Time
for a arbitrary year. Basically, I want to have code similar to the
following:

Dim StartDaylightDate As Date
Dim StartStandardDate As Date
Dim TestDate As Date
TestDate = DateSerial(2008, 6, 15)

StartDaylightDate = SomeFunction(Year(TestDate))
StartStandardDate = SomeFunction(Year(TestDate))
If (TestDate >= StartDaylightTime) And (TestDate < StartStandardTime) Then
   ' Return True
Else
   ' Return False
End If

It's the "SomeFunction" that I'm searching for.

Thank you for ANY advice.

Signature

Cordially,
Chip Pearson
Pearson Software Consulting, LLC
www.cpearson.com
(email address is on the web site)

Bob Butler - 22 Dec 2006 13:52 GMT
<cut>
> This clearly doesn't work The help isn't very clear, but it was my
> understanding that if I set the values of TZI.DaylightDate to the
> value as shown above, GetTimeZoneInformation would populate the
> TZI.DaylightDate and TZI.StandardDate with the dates of the start of
> Daylight and Standard times.

Calling the API function returns values similar to what you have set, it
doesn't return the specific dates.  You'd need to translate the "day d of
week w of month m" into a date for the specific year you are interested in.

Keep in mind that as of 2007 the values are changing and after you're system
is updated with the new start & end points then calculations based on that
for previous years are going to be wrong.

Signature

Reply to the group so all can participate
VB.Net: "Fool me once..."

Tony Proctor - 26 Dec 2006 21:39 GMT
I had to do this recently, and found a few interesting twists in the plot.

Firstly, the date/times at which standard/daylight-saving times begin are
not real ones, they're encoded ones. You cannot just call DateSerial using
their fields. Let me know if you want the conversion algorithm. The old docs
are woefully inadequate, but I did find some updated ones. Plus I found some
supposed VB samples on the Internet which were totally wrong and obviously
untested.

The second issue - which I never resolved - was how is it possible to
convert, say, a time of 1am on a day when the clocks go back at 2am. There
are effectively two instances of 1am that day: standard and daylight-saving,
and it's not possible for an API to know which you've given it (without an
extra parameter).

I had to write a function that does what you're trying, but for an arbitrary
timezone that may not be the current one. I did consider converting the
specified local time to UTC twice - once with the daylight-saving data
turned off - and test whether the two results were different. However, I
elected, in the end, to do pretty much what you're doing, i.e. just test
against the date/times at which the changeover occurs.

   Tony Proctor

> I need to write a function that will return True or False indicating whether
> a specified date is in the Daylight Savings Time period for that year. The
[quoted text clipped - 34 lines]
> Private Const TIME_ZONE_ID_DAYLIGHT = 2
> Private Const TIME_ZONE_ID_INVALID = -1

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
> Public Function IsDateInDST(DateVal As Long) As Boolean
>
[quoted text clipped - 22 lines]
>
> End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'

> This clearly doesn't work The help isn't very clear, but it was my
> understanding that if I set the values of TZI.DaylightDate to the value as
[quoted text clipped - 22 lines]
>
> Thank you for ANY advice.
Tony Proctor - 27 Dec 2006 14:58 GMT
These might be useful to yourself Chip, or anyone else reading this thread
later. They're extracted from a bigger timezone class I have here.
tTimeZoneInfo is a local TIME_ZONE_INFORMATION variable representing the
selected timezone.

'=====================
Private Function dLoadChangePoint(tDateTime As SYSTEMTIME) As Date
' Loads a daylight-saving changeover date/time (as encoded in
TIME_ZONE_INFORMATION) into a VB Date/time
Dim dTemp As Date
Dim dFirstWeekday As Long           'Weekday of 1st day in month (Sun=0,
Sat=6)

   With tDateTime
       If .wMonth = 0 Then
           oLocale.Error lErrNoDaylightSaving, TypeName(Me)
       Else
           If .wYear > 0 Then
               dTemp = DateSerial(.wYear, .wMonth, .wDay)
           Else
               Select Case .wDay
               Case 1 To 4:        'Week 1 to week 4
                   ' Calculate the first day in the month, and then
calculate the appropriate day
                   ' that the time zone change will occur at
                   dFirstWeekday = Weekday(DateSerial(Year(Date), .wMonth,
1), vbSunday) - 1
                   dTemp = DateSerial(Year(Date), .wMonth, _
                       ((.wDayOfWeek - dFirstWeekday) + (.wDay - 1) * 7) +
1)

               Case 5:             'Last week in month
                   ' Calculate the month's last day, then work back to the
appropriate weekday
                   dTemp = DateSerial(Year(Date), .wMonth + 1, 0)
                   dTemp = DateAdd("d", (.wDayOfWeek - (Weekday(dTemp,
vbSunday) - 1) - 7) Mod 7, dTemp)
               End Select
           End If
       End If

       dLoadChangePoint = dTemp + TimeSerial(.wHour, .wMinute, .wSecond)
   End With
End Function

Public Property Get DaylightStart() As Date
' Returns the date/time at which the transition from standard time to
daylight-saving
' time occurs, or the VB base date (30/12/1899) if no daylight-saving
defined
   If tTimeZoneInfo.DaylightDate.wMonth <> 0 Then
       DaylightStart = dLoadChangePoint(tTimeZoneInfo.DaylightDate)
   End If
End Property

Public Property Get StandardStart() As Date
' Returns the date/time at which the transition from daylight-saving time to
standard
' time occurs, or the VB base date (30/12/1899) if no daylight-saving
defined
   If tTimeZoneInfo.StandardDate.wMonth <> 0 Then
       StandardStart = dLoadChangePoint(tTimeZoneInfo.StandardDate)
   End If
End Property

Public Function InDayLightSaving(dDateTime As Date) As Boolean
' Determines whether a local time is in "daylight saving" mode or not

   If tTimeZoneInfo.DaylightDate.wMonth <> 0 Then
       InDayLightSaving = (dDateTime >=
dLoadChangePoint(tTimeZoneInfo.DaylightDate) And _
           dDateTime < dLoadChangePoint(tTimeZoneInfo.StandardDate))
   End If
End Function
'=================

The following notes are from some updated MSDN docs, and explain how the
changeover times are encoded...

"To select the correct day in the month, set the wYear member to zero, the
wHour and wMinute members to the transition time, the wDayOfWeek member to
the appropriate weekday, and the wDay member to indicate the occurrence of
the day of the week within the month (1 to 5, where 5 indicates the final
occurrence during the month if that day of the week does not occur 5 times).

Using this notation, specify the 2:00a.m. on the first Sunday in April as
follows: wHour = 2, wMonth = 4, wDayOfWeek = 0, wDay = 1. Specify 2:00a.m.
on the last Thursday in October as follows: wHour = 2, wMonth = 10,
wDayOfWeek = 4, wDay = 5."

   Tony Proctor

> I had to do this recently, and found a few interesting twists in the plot.
>
[quoted text clipped - 60 lines]
> > Private Const TIME_ZONE_ID_DAYLIGHT = 2
> > Private Const TIME_ZONE_ID_INVALID = -1

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
> '
> > Public Function IsDateInDST(DateVal As Long) As Boolean
[quoted text clipped - 23 lines]
> >
> > End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
> '
> >
[quoted text clipped - 27 lines]
> >
> > Thank you for ANY advice.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.