将UTC时间转换为本地时间

时间:2014-05-28 06:02:08

标签: vba ms-access

我有一个MS Access应用程序,用于两个不同的时区。差异是7个小时。我需要找到两个办公室都关闭的时间,这样我就可以关闭他们的数据库了,我可以做紧凑的维修并备份它们。

所以我不需要创建两个分离前端,我告诉密切数据库一个在下午1000点而另一个在凌晨4点我发现我可以说在世界贸易组织上午00:30关闭数据库。 但我不知道如何在Local中转换同一个。 现在我关闭数据库的代码如下所示:

Private Sub Form_Timer()
Dim RunAtLocalTime As String

RunAtLocalTime = Format(Now(), "HH:MM:SS")
If RunAtLocalTime = ("00:00:00") Then
        DoCmd.Quit
End If
End Sub

我想做这样的事情:

Private Sub Form_Timer()
Dim RunAtLocalTime As String
Dim UTCTIME As 

'''RunAtLocalTime = Convert(UTCTIME)
 RunAtLocalTime = Format(Now(), "HH:MM:SS")
 If RunAtLocalTime = ("00:00:00") Then
        DoCmd.Quit
End If
End Sub

4 个答案:

答案 0 :(得分:6)

Caution!

警惕您用于时区转换的方法,包括与UTC标准之间的转换。时区规则(包括夏令时的差异)开始时令人困惑,因为它们不仅因地区或国家而异,而且在某些情况下由州或县变化。

为了进一步混淆问题,规则不断发展,因此出于合乎逻辑的原因(如地球的剩余一半,希望,正在逐步消除夏令时),有时不那么合乎逻辑(国家领导人随心所欲地改变规则),和其他时间不正确地沟通(case study: Turkey's 2015 Chaos)。

即使加拿大/美国也有major change in 2007,编码人员经常忘记考虑。 本网站上的其他解决方案(或此页面!)错误估算是某些情况或时间范围。

理想情况下,我们都会使用相同的方法从同一个地方获取信息。未来和历史时区信息的权限被视为由tz database

发布的related codeiana.org

Solution!

以下转换方法考虑了所有夏令时和时区差异,我通过冗长的分析和权威文档(例如Unicode Common Locale Data Repository)努力确认。

我最小化了空间和效率,仅包括与我的目的相关的功能:UTC时间和本地时间之间的转换,以及Epoch 时间戳和本地时间之间的转换。这是Tim Hall的code的改编 Epoch时间戳,也称为Unix时间是自1970年1月1日以来的秒数,并在许多API和其他API中用作标准时间格式编程资源。 epochconverter.com Wikipedia的更多信息。

我建议将它放在一个模块中。

Option Explicit
'UTC/Local Time Conversion
'Adapted from code by Tim Hall published at https://github.com/VBA-tools/VBA-UtcConverter

Option Explicit
'UTC/Local Time Conversion
'Adapted from code by Tim Hall published at github.com/VBA-tools/VBA-UtcConverter

'PUBLIC FUNCTIONS:
'    - UTCtoLocal(utc_UtcDate As Date) As Date     converts UTC datetimes to local
'    - LocalToUTC(utc_LocalDate As Date) As Date   converts local DateTime to UTC
'    - TimestampToLocal(st As String) As Date      converts epoch timestamp to Local Time
'    - LocalToTimestamp(dt as date) as String      converts Local Time to timestamp
'Accuracy confirmed for several variations of time zones & DST rules. (ashleedawg)
'===============================================================================

Private Type utc_SYSTEMTIME
    utc_wYear As Integer: utc_wMonth As Integer: utc_wDayOfWeek As Integer: utc_wDay As Integer
    utc_wHour As Integer: utc_wMinute As Integer: utc_wSecond As Integer: utc_wMilliseconds As Integer
End Type

Private Type utc_TIME_ZONE_INFORMATION
    utc_Bias As Long: utc_StandardName(0 To 31) As Integer: utc_StandardDate As utc_SYSTEMTIME: utc_StandardBias As Long
    utc_DaylightName(0 To 31) As Integer: utc_DaylightDate As utc_SYSTEMTIME: utc_DaylightBias As Long
End Type

'http://msdn.microsoft.com/library/windows/desktop/ms724421.aspx /ms724949.aspx /ms725485.aspx
Private Declare PtrSafe Function utc_GetTimeZoneInformation Lib "kernel32" Alias "GetTimeZoneInformation" _
    (utc_lpTimeZoneInformation As utc_TIME_ZONE_INFORMATION) As Long
Private Declare PtrSafe Function utc_SystemTimeToTzSpecificLocalTime Lib "kernel32" Alias "SystemTimeToTzSpecificLocalTime" _
    (utc_lpTimeZoneInformation As utc_TIME_ZONE_INFORMATION, utc_lpUniversalTime As utc_SYSTEMTIME, utc_lpLocalTime As utc_SYSTEMTIME) As Long
Private Declare PtrSafe Function utc_TzSpecificLocalTimeToSystemTime Lib "kernel32" Alias "TzSpecificLocalTimeToSystemTime" _
    (utc_lpTimeZoneInformation As utc_TIME_ZONE_INFORMATION, utc_lpLocalTime As utc_SYSTEMTIME, utc_lpUniversalTime As utc_SYSTEMTIME) As Long

Private Function utc_DateToSystemTime(utc_Value As Date) As utc_SYSTEMTIME ' "Helper Function" for Public subs (below)
    With utc_DateToSystemTime
        .utc_wYear = Year(utc_Value): .utc_wMonth = Month(utc_Value): .utc_wDay = Day(utc_Value)
        .utc_wHour = Hour(utc_Value): .utc_wMinute = Minute(utc_Value): .utc_wSecond = Second(utc_Value): .utc_wMilliseconds = 0
    End With
End Function

Private Function utc_SystemTimeToDate(utc_Value As utc_SYSTEMTIME) As Date ' "Helper Function" for Public Functions (below)
    utc_SystemTimeToDate = DateSerial(utc_Value.utc_wYear, utc_Value.utc_wMonth, utc_Value.utc_wDay) + _
        TimeSerial(utc_Value.utc_wHour, utc_Value.utc_wMinute, utc_Value.utc_wSecond)
End Function

'===============================================================================
Public Function TimestampToLocal(st As String) As Date
    TimestampToLocal = UTCtoLocal((Val(st) / 86400) + 25569)
End Function
Public Function LocalToTimestamp(dt As Date) As String
    LocalToTimestamp = (LocalToUTC(dt) - 25569) * 86400
End Function

Public Function UTCtoLocal(utc_UtcDate As Date) As Date
    On Error GoTo errorUTC
    Dim utc_TimeZoneInfo As utc_TIME_ZONE_INFORMATION, utc_LocalDate As utc_SYSTEMTIME
    utc_GetTimeZoneInformation utc_TimeZoneInfo
    utc_SystemTimeToTzSpecificLocalTime utc_TimeZoneInfo, utc_DateToSystemTime(utc_UtcDate), utc_LocalDate
    UTCtoLocal = utc_SystemTimeToDate(utc_LocalDate)
    Exit Function
errorUTC:
    Debug.Print "UTC parsing error: " & Err.Number & " - " & Err.Description: Stop
End Function

Public Function LocalToUTC(utc_LocalDate As Date) As Date
    On Error GoTo errorUTC
    Dim utc_TimeZoneInfo As utc_TIME_ZONE_INFORMATION, utc_UtcDate As utc_SYSTEMTIME
    utc_GetTimeZoneInformation utc_TimeZoneInfo
    utc_TzSpecificLocalTimeToSystemTime utc_TimeZoneInfo, utc_DateToSystemTime(utc_LocalDate), utc_UtcDate
    LocalToUTC = utc_SystemTimeToDate(utc_UtcDate)
    Exit Function
errorUTC:
    Debug.Print "UTC conversion error: " & Err.Number & " - " & Err.Description: Stop
End Function

我知道这似乎是一个非常多的代码,只是为了增加/减少几个小时,但我精心研究,希望找到一个可靠的更短/更简单的方法,保证准确与当前和历史时期,但没有成功。使用这种方法所需要的只是一份副本&糊。 ☺

示例用法:

Sub testTZC()
'(Note that "Local time" in these examples is Vancouver/Los Angeles)
    MsgBox LocalToUTC("2004-04-04 01:00") 'returns: 2004-04-04 9:00:00 AM (not DST)
    MsgBox LocalToUTC("2004-04-04 03:00") 'returns: 2004-04-04 10:00:00 AM (is DST)
    MsgBox UTCtoLocal("2000-01-01 00:00") 'returns: 1999-12-31 4:00:00 PM
    MsgBox TimestampToLocal("1234567890") 'returns: 2009-02-13 3:31:30 PM
    MsgBox LocalToTimestamp("April 17, 2019 7:45:55 PM") 'returns: 1555555555
End Sub

答案 1 :(得分:5)

将本地时间转换为UTC,反之亦然:

#If VBA7 Then
  Private Declare PtrSafe Function LocalFileTimeToFileTime Lib "kernel32" (src@, tgt@) As Long
  Private Declare PtrSafe Function FileTimeToLocalFileTime Lib "kernel32" (src@, tgt@) As Long
#Else
  Private Declare Function LocalFileTimeToFileTime Lib "kernel32" (src@, tgt@) As Long
  Private Declare Function FileTimeToLocalFileTime Lib "kernel32" (src@, tgt@) As Long
#End If

Public Function ToUTC(ByVal datetime As Date) As Date
  Dim ftLoc@, ftUtc@
  ftLoc = (datetime - #1/1/1601#) * 86400000
  LocalFileTimeToFileTime ftLoc, ftUtc
  ToUTC = ftUtc / 86400000# + #1/1/1601#
End Function

Public Function FromUTC(ByVal datetime As Date) As Date
  Dim ftUtc@, ftLoc@
  ftUtc = (datetime - #1/1/1601#) * 86400000
  FileTimeToLocalFileTime ftUtc, ftLoc
  FromUTC = ftLoc / 86400000# + #1/1/1601#
End Function

答案 2 :(得分:4)

我找到了以下功能:

这个返回UTC时区偏移量:

Option Compare Database
Option Explicit

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


Private Type SystemTime
        intYear As Integer
        intMonth As Integer
        intwDayOfWeek As Integer
        intDay As Integer
        intHour As Integer
        intMinute As Integer
        intSecond As Integer
        intMilliseconds As Integer
End Type


Private Type TimeZoneInfo
        lngBias As Long
        intStandardName(32) As Integer
        intStandardDate As SystemTime
        intStandardBias As Long
        intDaylightName(32) As Integer
        intDaylightDate As SystemTime
        intDaylightBias As Long
End Type

Public Function GetUTCOffset() As Date
    Dim lngRet As Long
    Dim udtTZI As TimeZoneInfo

    lngRet = GetTimeZoneInformation(udtTZI)
    GetUTCOffset = udtTZI.lngBias / 60 / 24
End Function

来源:[此网站](修改链接不再有效,已删除)

这个将时间转换为GMT的那个:

Option Explicit
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(31) As Integer
    StandardDate As SYSTEMTIME
    StandardBias As Long
    DaylightName(31) As Integer
    DaylightDate As SYSTEMTIME
    DaylightBias As Long
End Type

Private Declare Function GetTimeZoneInformation Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
'Purpose     :  Converts local time to GMT.
'Inputs      :  dtLocalDate                 The local data time to return as GMT.
'Outputs     :  Returns the local time in GMT.
'Author      :  Andrew Baker
'Date        :  13/11/2002 10:16
'Notes       :
'Revisions   :

Public Function ConvertLocalToGMT(dtLocalDate As Date) As Date
    Dim lSecsDiff As Long

    'Get the GMT time diff
    lSecsDiff = GetLocalToGMTDifference()
    'Return the time in GMT
    ConvertLocalToGMT = DateAdd("s", -lSecsDiff, dtLocalDate)
End Function

'Purpose     :  Converts GMT time to local time.
'Inputs      :  dtLocalDate                 The GMT data time to return as local time.
'Outputs     :  Returns GMT as local time.
'Author      :  Andrew Baker
'Date        :  13/11/2002 10:16
'Notes       :
'Revisions   :

Public Function ConvertGMTToLocal(gmtTime As Date) As Date
    Dim Differerence As Long

    Differerence = GetLocalToGMTDifference()
    ConvertGMTToLocal = DateAdd("s", Differerence, gmtTime)
End Function

'Purpose     :  Returns the time lDiff between local and GMT (secs).
'Inputs      :  dtLocalDate                 The local data time to return as GMT.
'Outputs     :  Returns the local time in GMT.
'Author      :  Andrew Baker
'Date        :  13/11/2002 10:16
'Notes       :  A positive number indicates your ahead of GMT.
'Revisions   :

Public Function GetLocalToGMTDifference() As Long
    Const TIME_ZONE_ID_INVALID& = &HFFFFFFFF
    Const TIME_ZONE_ID_STANDARD& = 1
    Const TIME_ZONE_ID_UNKNOWN& = 0
    Const TIME_ZONE_ID_DAYLIGHT& = 2

    Dim tTimeZoneInf As TIME_ZONE_INFORMATION
    Dim lRet As Long
    Dim lDiff As Long

    'Get time zone info
    lRet = GetTimeZoneInformation(tTimeZoneInf)

    'Convert diff to secs
    lDiff = -tTimeZoneInf.Bias * 60
    GetLocalToGMTDifference = lDiff

    'Check if we are in daylight saving time.
    If lRet = TIME_ZONE_ID_DAYLIGHT& Then
        'In daylight savings, apply the bias
        If tTimeZoneInf.DaylightDate.wMonth <> 0 Then
            'if tTimeZoneInf.DaylightDate.wMonth = 0 then the daylight
            'saving time change doesn't occur
            GetLocalToGMTDifference = lDiff - tTimeZoneInf.DaylightBias * 60
        End If
    End If
End Function

来源:this site

我认为第二个也使用第一个。

我相信这两种情况都符合您的需求。

答案 3 :(得分:0)

这是我的项目的一项核心功能,目的是最大限度地利用Windows中的时区信息。

' Converts a present UtcDate from Coordinated Universal Time (UTC) to local time.
' If IgnoreDaylightSetting is True, returned time will always be standard time.
'
' For dates not within the current year, use the function DateFromDistantUtc.
'
' 2017-11-27. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function DateFromUtc( _
    ByVal UtcDate As Date, _
    Optional ByVal IgnoreDaylightSetting As Boolean) _
    As Date

    Dim LocalBias   As Long
    Dim LocalDate   As Date

    ' Find the local time using standard bias.
    LocalBias = LocalBiasTimezonePresent(UtcDate, True)
    LocalDate = DateRemoteBias(UtcDate, UtcBias, LocalBias)
    If IgnoreDaylightSetting = False Then
        ' The local time should be returned as daylight time.
        If IsCurrentDaylightSavingTime(LocalDate) Then
            ' The local time is daylight time.
            ' Find bias for daylight time.
            LocalBias = LocalBiasTimezonePresent(LocalDate, IgnoreDaylightSetting)
            ' Find the local time using daylight bias.
            LocalDate = DateRemoteBias(UtcDate, UtcBias, LocalBias)
        End If
    End If

    DateFromUtc = LocalDate

End Function

它调用了一系列支持功能,这些功能将在此处发布。可以在GitHub上找到包含Access和Excel的完整代码和演示的项目:VBA.Timezone-Windows