Get Timezone Information in VBA (Excel)

前端 未结 7 966
春和景丽
春和景丽 2020-11-29 09:27

I would like to determine a time offset to GMT/UTC (including daylight saving time) for different countries at a specific date in VBA. Any ideas?

EDIT (from self-an

相关标签:
7条回答
  • 2020-11-29 10:02

    Based on Julian Hess excellent recommendation to use Outlook capabilities, I have build this module, which works with Access and Excel.

    Option Explicit
    
    'mTimeZones by Patrick Honorez --- www.idevlop.com
    'with the precious help of Julian Hess https://stackoverflow.com/a/45510712/78522
    'You can reuse but please let all the original comments including this one.
    
    'This modules uses late binding and therefore should not require an explicit reference to Outlook,
    'however Outlook must be properly installed and configured on the machine using this module
    'Module works with Excel and Access
    
    Private oOutl As Object 'keep Outlook reference active, to save time in recurring calls
    Private oOutlTimeZones As Object 'keep Outlook reference active, to save time in recurring calls
    ' seems to drop the reference if use previous scheme of returning boolean
    ' returning the actual object is more correct in any case
    Private Function GetOutlookTimeZones() As Object
        If oOutl Is Nothing Or oOutlTimeZones Is Nothing Then
            Debug.Print "~"
            On Error Resume Next
            Err.Clear
            Set oOutl = GetObject(, "Outlook.Application")
            If Err.Number Then
                Err.Clear
                Set oOutl = CreateObject("Outlook.Application")
            End If
            Set oOutlTimeZones = oOutl.TimeZones
        End If
        Set GetOutlookTimeZones = oOutlTimeZones
        On Error GoTo 0
    End Function
    
    Function ConvertTime(DT As Date, Optional TZfrom As String = "Central Standard Time", _
                                     Optional TZto As String = "W. Europe Standard Time") As Date
    'convert datetime with hour from Source time zone to Target time zone
    'valid Source & Target time zones can be found in your registry under: HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones/
    'this version using Outlook, properly handles Dailight Saving Times, including for past and future dates
    'it includes a fix for the fact that ConvertTime seems to strip the seconds
    'krammy85 2019-01-25 Edit: Outlook rounds minutes when it strips seconds, so modified code to strip seconds (without rounding) prior to running Outlook's ConvertTime.
        Dim sourceTZ As Object
        Dim destTZ As Object
        Dim seconds As Single
        Dim DT_SecondsStripped As Date
        Dim oOutlTimeZones As Object: Set oOutlTimeZones = GetOutlookTimeZones()
        If Not (oOutlTimeZones Is Nothing) Then
            'fix for ConvertTime stripping the seconds
            seconds = Second(DT) / 86400    'save the seconds as DateTime (86400 = 24*60*60)
            DT_SecondsStripped = DT - seconds
            Set sourceTZ = oOutlTimeZones.Item(TZfrom)
            Set destTZ = oOutlTimeZones.Item(TZto)
            ConvertTime = oOutlTimeZones.ConvertTime(DT_SecondsStripped, sourceTZ, destTZ) + seconds    'add the stripped seconds
        End If
    End Function
    
    ' returns number of minutes ahead of UTC (positive number) or behind
    Function GetOffsetAt(DT As Date, TZfrom As String) As Long
        Dim utc_DT As Date: utc_DT = ConvertTime(DT, TZfrom, "UTC")
        GetOffsetAt = DateDiff("n", utc_DT, DT)
    End Function
    
    Sub test_ConvertTime()
        Dim t As Date: t = #8/23/2017 6:15:05 AM#
        Debug.Print t, ConvertTime(t), Format(t - ConvertTime(t), "h")
        Debug.Print t, ConvertTime(t, "Central Standard Time", "W. Europe Standard Time"), Format(t - ConvertTime(t), "h")
    End Sub
    
    Sub test_DumpTZs()
        Dim TZ As Object: For Each TZ In GetOutlookTimeZones()
            Debug.Print "TZ:", TZ.Id, TZ.Name
        Next TZ
    End Sub
    
    0 讨论(0)
提交回复
热议问题