Как получить текущую дату и время в формате UTC из макроса Excel VBA

StackOverflow https://stackoverflow.com/questions/1600875

Вопрос

Есть ли способ в макросе Excel VBA получить текущую дату и время в формате UTC?

Я могу позвонить Now() чтобы узнать текущее время в местном часовом поясе;есть ли общий способ затем преобразовать это в UTC?

Спасибо

Это было полезно?

Решение

http://excel.tips.net/Pages/T002185_Automatically_Converting_to_GMT.html

На этой странице есть макрос с методом LocalTimeToUTC.Похоже, это сработало бы.Также несколько примеров формул, если вы хотите пойти по этому пути.

Редактировать - Другая ссылка. http://www.cpearson.com/excel/TimeZoneAndDaylightTime.aspx На этой странице есть несколько методов определения даты / времени.Выбирай свой яд.Любое из них должно сработать, но я чувствую, что второе красивее.;)

Другие советы

Проще говоря, вы можете использовать COM-объект для получения информации о времени UTC.

Dim dt As Object, utc As Date
Set dt = CreateObject("WbemScripting.SWbemDateTime")
dt.SetVarDate Now
utc = dt.GetVarDate(False)

Конечно, этот вопрос устарел, но я просто потратил некоторое время на составление некоторого чистого кода на основе этого, и я хотел опубликовать его здесь на случай, если кто-нибудь, наткнувшийся на эту страницу, сочтет его полезным.

Создайте новый модуль в среде разработки Excel VBA IDE (при необходимости присвоив ему имя UtcConverter или что бы вы ни предпочли на странице свойств) и вставьте приведенный ниже код.

HTH

Option Explicit

' Use the PtrSafe attribute for x64 installations
Private Declare PtrSafe Function FileTimeToLocalFileTime Lib "Kernel32" (lpFileTime As FILETIME, ByRef lpLocalFileTime As FILETIME) As Long
Private Declare PtrSafe Function LocalFileTimeToFileTime Lib "Kernel32" (lpLocalFileTime As FILETIME, ByRef lpFileTime As FILETIME) As Long
Private Declare PtrSafe Function SystemTimeToFileTime Lib "Kernel32" (lpSystemTime As SYSTEMTIME, ByRef lpFileTime As FILETIME) As Long
Private Declare PtrSafe Function FileTimeToSystemTime Lib "Kernel32" (lpFileTime As FILETIME, ByRef lpSystemTime As SYSTEMTIME) As Long

Public Type FILETIME
  LowDateTime As Long
  HighDateTime As Long
End Type

Public Type SYSTEMTIME
  Year As Integer
  Month As Integer
  DayOfWeek As Integer
  Day As Integer
  Hour As Integer
  Minute As Integer
  Second As Integer
  Milliseconds As Integer
End Type


'===============================================================================
' Convert local time to UTC
'===============================================================================
Public Function UTCTIME(LocalTime As Date) As Date
  Dim oLocalFileTime As FILETIME
  Dim oUtcFileTime As FILETIME
  Dim oSystemTime As SYSTEMTIME

  ' Convert to a SYSTEMTIME
  oSystemTime = DateToSystemTime(LocalTime)

  ' 1. Convert to a FILETIME
  ' 2. Convert to UTC time
  ' 3. Convert to a SYSTEMTIME
  Call SystemTimeToFileTime(oSystemTime, oLocalFileTime)
  Call LocalFileTimeToFileTime(oLocalFileTime, oUtcFileTime)
  Call FileTimeToSystemTime(oUtcFileTime, oSystemTime)

  ' Convert to a Date
  UTCTIME = SystemTimeToDate(oSystemTime)
End Function



'===============================================================================
' Convert UTC to local time
'===============================================================================
Public Function LOCALTIME(UtcTime As Date) As Date
  Dim oLocalFileTime As FILETIME
  Dim oUtcFileTime As FILETIME
  Dim oSystemTime As SYSTEMTIME

  ' Convert to a SYSTEMTIME.
  oSystemTime = DateToSystemTime(UtcTime)

  ' 1. Convert to a FILETIME
  ' 2. Convert to local time
  ' 3. Convert to a SYSTEMTIME
  Call SystemTimeToFileTime(oSystemTime, oUtcFileTime)
  Call FileTimeToLocalFileTime(oUtcFileTime, oLocalFileTime)
  Call FileTimeToSystemTime(oLocalFileTime, oSystemTime)

  ' Convert to a Date
  LOCALTIME = SystemTimeToDate(oSystemTime)
End Function



'===============================================================================
' Convert a Date to a SYSTEMTIME
'===============================================================================
Private Function DateToSystemTime(Value As Date) As SYSTEMTIME
  With DateToSystemTime
    .Year = Year(Value)
    .Month = Month(Value)
    .Day = Day(Value)
    .Hour = Hour(Value)
    .Minute = Minute(Value)
    .Second = Second(Value)
  End With
End Function



'===============================================================================
' Convert a SYSTEMTIME to a Date
'===============================================================================
Private Function SystemTimeToDate(Value As SYSTEMTIME) As Date
  With Value
    SystemTimeToDate = _
      DateSerial(.Year, .Month, .Day) + _
      TimeSerial(.Hour, .Minute, .Second)
  End With
End Function

Если все, что вам нужно, - это текущее время, вы можете сделать это с помощью Получает системное время, что требует меньшего количества вызовов Win32.Это дает вам временную структуру с точностью до миллисекунды, которую вы можете отформатировать так, как вам хотелось бы:

Private Declare PtrSafe Sub GetSystemTime Lib "Kernel32" (ByRef lpSystemTime As SYSTEMTIME)

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

Использование:

Dim nowUtc As SYSTEMTIME
Call GetSystemTime(nowUtc) 
' nowUtc is now populated with the current UTC time. Format or convert to Date as needed.

Если вам также необходимо учитывать переход на летнее время, вам может оказаться полезным следующий код:

Option Explicit

'''''''''''''''''''''''''''''''''''''''''''''''''''''
' Windows API Structures
'''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Type SYSTEM_TIME
    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 SYSTEM_TIME
    StandardBias As Long
    DaylightName(0 To 31) As Integer
    DaylightDate As SYSTEM_TIME
    DaylightBias As Long
End Type    

'''''''''''''''''''''''''''''''''''''''''''''''''''''
' Windows API Imports
'''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Declare Function GetTimeZoneInformation Lib "kernel32" _
    (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long

Private Declare Function TzSpecificLocalTimeToSystemTime Lib "kernel32" _
    (lpTimeZoneInformation As TIME_ZONE_INFORMATION, lpLocalTime As SYSTEM_TIME, lpUniversalTime As SYSTEM_TIME) As Integer

Function ToUniversalTime(localTime As Date) As Date
    Dim timeZoneInfo As TIME_ZONE_INFORMATION

    GetTimeZoneInformation timeZoneInfo

    Dim localSystemTime As SYSTEM_TIME
    With localSystemTime
        .wYear = Year(localTime)
        .wMonth = Month(localTime)
        .wDay = Day(localTime)
    End With

    Dim utcSystemTime As SYSTEM_TIME

    If TzSpecificLocalTimeToSystemTime(timeZoneInfo, localSystemTime, utcSystemTime) <> 0 Then
        ToUniversalTime = SystemTimeToVBTime(utcSystemTime)
    Else
        err.Raise 1, "WINAPI", "Windows API call failed"
    End If

End Function

Private Function SystemTimeToVBTime(systemTime As SYSTEM_TIME) As Date
    With systemTime
        SystemTimeToVBTime = DateSerial(.wYear, .wMonth, .wDay) + _
                TimeSerial(.wHour, .wMinute, .wSecond)
    End With
End Function

Мой проект Access работает в основном с таблицами Access, связанными с таблицами MS SQL Server.Это проект DAO, и у меня возникли проблемы даже с возвратом SQL sproc с GETUTCDATE().Но моим решением было следующее.

-- Create SQL table with calculated field for UTCDate
CREATE TABLE [dbo].[tblUTCDate](
    [ID] [int] NULL,
    [UTCDate]  AS (getutcdate())
) ON [PRIMARY]
GO

Создайте таблицу доступа dbo_tblUTCDate, связанную через ODBC с таблицей SQL tblUTCDate.

Создайте запрос доступа для выбора из таблицы Access.Я назвал это qryUTCDate.

SELECT dbo_tblUTCDate.UTCDate FROM dbo_tblUTCDate

В VBA:

Dim db as DAO.database, rs AS Recordset
Set rs = db.OpenRecordset("qryUTCDate")
Debug.Print CStr(rs!UTCDATE)
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top