VB. Как узнать свой часовой пояс (смещение относительно UTC)

Здесь обсуждаются вопросы по программированию на Visual Basic.


Модератор: UncleFather

Аватара пользователя
UncleFather
Site Admin
Сообщения: 1505
Зарегистрирован: 17 авг 2004 16:20, Вт
Контактная информация:

VB. Как узнать свой часовой пояс (смещение относительно UTC)

Сообщение UncleFather »

Задача:

Необходимо узнать свой часовой пояс - смещение своего времени относительно времени UTC в Visual Basic или в Visual Basic for Applications, то есть получить циферку с плюсом или минусом означающую на сколько местные часы сдвинуты относительно универсального координированного времени UTC (всемирного времени).

Решение:

Основной проблемой является то, что, как ни странно, ни в VB, ни в VBA нет такой функции, чтобы узнать свой часовой пояс. Поэтому приходится пользоваться Windows API функцией GetTimeZoneInformation.

Visual Basic код взят отсюда. Полный модуль bas, включающий в себя еще несколько функций для работы с часовыми поясами можно скачать здесь или прямо отсюда:

modTimeZones.zip
(2.09 КБ) 662 скачивания

Итак, приступим (для примера будем работать в MS Excel Visual Basic for Applications):

  1. Создаем в рабочей книге MS Excel модуль (если его еще нет)

  2. Вставляем в этот модуль

    VBA код:

    Код: Выделить всё

    Option Explicit
    Option Compare Text
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' modTimeZones
    ' By Chip Pearson, chip@cpearson.com, www.cpearson.com
    ' Date: 2-April-2008
    ' Page Specific URL: www.cpearson.com/Excel/TimeZoneAndDaylightTime.aspx
    '
    ' This module contains functions related to time zones and GMT times.
    '   Terms:
    '   -------------------------
    '   GMT = Greenwich Mean Time. Many applications use the term
    '       UTC (Universal Coordinated Time). GMT and UTC are
    '       interchangable in meaning,
    '   Local Time = The local "wall clock" time of day, that time that
    '       you would set a clock to.
    '   DST = Daylight Savings Time
    
    '   Functions In This Module:
    '   -------------------------
    '       LocalOffsetFromGMT
    '           Returns the number of minutes or hours that are to be added to
    '           the local time to get GMT. Optionally adjusts for DST.
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
    
    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
    
    Public Enum TIME_ZONE
        TIME_ZONE_ID_INVALID = 0
        TIME_ZONE_STANDARD = 1
        TIME_ZONE_DAYLIGHT = 2
    End Enum
        
    '''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Required Windows API Declares
    '''''''''''''''''''''''''''''''''''''''''''''''''''''
    #If Win64 Then
        #If VBA7 Then    ' Windows x64, Office 2010
            Private Declare PtrSafe Function GetTimeZoneInformation Lib "kernel32" _
                (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
            
            Private Declare PtrSafe Sub GetSystemTime Lib "kernel32" _
                (lpSystemTime As SYSTEMTIME)
        #Else    ' Windows x64,Office 2003-2007
            Private Declare Function GetTimeZoneInformation Lib "kernel32" _
                (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
            
            Private Declare Sub GetSystemTime Lib "kernel32" _
                (lpSystemTime As SYSTEMTIME)
        #End If
    #Else
        #If VBA7 Then    ' Windows x86, Office 2010
            Private Declare PtrSafe Function GetTimeZoneInformation Lib "kernel32" _
                (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
            
            Private Declare PtrSafe Sub GetSystemTime Lib "kernel32" _
                (lpSystemTime As SYSTEMTIME)
        #Else    ' Windows x86, Office 2003-2007
            Private Declare Function GetTimeZoneInformation Lib "kernel32" _
                (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
            
            Private Declare Sub GetSystemTime Lib "kernel32" _
                (lpSystemTime As SYSTEMTIME)
        #End If
    #End If
    
    
    Public Function LocalOffsetFromGMT(Optional AsHours As Boolean = False, _
        Optional AdjustForDST As Boolean = False) As Long
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' LocalOffsetFromGMT
    ' This returns the amount of time in minutes (if AsHours is omitted or
    ' false) or hours (if AsHours is True) that should be added to the
    ' local time to get GMT. If AdjustForDST is missing or false,
    ' the unmodified difference is returned. (e.g., Kansas City to London
    ' is 6 hours normally, 5 hours during DST. If AdjustForDST is False,
    ' the resultif 6 hours. If AdjustForDST is True, the result is 5 hours
    ' if DST is in effect.)
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
    Dim TBias As Long
    Dim TZI As TIME_ZONE_INFORMATION
    Dim DST As TIME_ZONE
    DST = GetTimeZoneInformation(TZI)
    
    If DST = TIME_ZONE_DAYLIGHT Then
        If AdjustForDST = True Then
            TBias = -(TZI.Bias + TZI.DaylightBias)
        Else
            TBias = -TZI.Bias
        End If
    Else
        TBias = -TZI.Bias
    End If
    If AsHours = True Then
        TBias = TBias / 60
    End If
    
    LocalOffsetFromGMT = TBias
    
    End Function
    
    
  3. Пользуемся созданной нами функцией LocalOffsetFromGMT() в любом месте этой рабочей книги MS Excel (или вообще из любой рабочей книги MS Excel, если модуль сохранен в личной книге макросов).

Пример:

Необходимо конвертировать дату и время (в формате Unix Datestamp) установки MS Windows, полученное из реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\InstallDate и помещенное в ячейку «A2» в обычный удобочитаемый формат, при этом учесть часовой пояс системы.

О том, как конвертировать из Unix Datestamp в формат MS Excel читаем здесь.

Остается только добавить в формулу поправку на наш часовой пояс. Но, поскольку функция LocalOffsetFromGMT() возвращает значение в минутах, а расчет в формуле в ячейке ведется в днях, то мы должны конвертировать это значение в дни, для чего используем коэффициент 60*24=1440.

Итак, окончательная формула в ячейке «A4» будет выглядеть так:

Код: Выделить всё

=A2/86400+LocalOffsetFromGMT()/1440+ДАТА(1970;1;1)

где:

  • A2 - адрес ячейки с временем в формате Unix Timestamp

  • 86400 - коэффициент, равный количеству секунд в одних сутках

  • ДАТА(1970;1;1) - дата 01 января 1970 года, с которой ведется отсчет Unix Timestamp

05.JPG

Alexander A. Manaeff©

Понравилась статья? Будем крайне признательны за репосты в соцсетях! Материально поддержать проект можно здесь

Мои странички:
ВКонтакте
Одноклассники
Youtube
Facebook
Instagram

Изображение
Изображение
Изображение
Изображение