UncleFather » 27 фев 2014 17:12, Чт
Задача:
Необходимо узнать свой часовой пояс - смещение своего времени относительно времени UTC в Visual Basic или в Visual Basic for Applications, то есть получить циферку с плюсом или минусом означающую на сколько местные часы сдвинуты относительно универсального координированного времени UTC (всемирного времени).
Решение:
Основной проблемой является то, что, как ни странно, ни в VB, ни в VBA нет такой функции, чтобы узнать свой часовой пояс. Поэтому приходится пользоваться Windows API функцией GetTimeZoneInformation.
Visual Basic код взят отсюда. Полный модуль bas, включающий в себя еще несколько функций для работы с часовыми поясами можно скачать здесь или прямо отсюда:
Итак, приступим (для примера будем работать в MS Excel Visual Basic for Applications):
-
Создаем в рабочей книге MS Excel модуль (если его еще нет)
-
Вставляем в этот модуль
Код: Выделить всё
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
-
Пользуемся созданной нами функцией 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
[b][size=150]Задача:[/size][/b]
Необходимо узнать свой часовой пояс - смещение своего времени относительно времени UTC в Visual Basic или в Visual Basic for Applications, то есть получить циферку с плюсом или минусом означающую на сколько местные часы сдвинуты относительно универсального координированного времени UTC (всемирного времени).
[b][size=150]Решение:[/size][/b]
Основной проблемой является то, что, как ни странно, ни в VB, ни в VBA нет такой функции, чтобы узнать свой часовой пояс. Поэтому приходится пользоваться Windows API функцией [b][i]GetTimeZoneInformation[/i][/b].
Visual Basic код взят [url=http://www.cpearson.com/excel/TimeZoneAndDaylightTime.aspx]отсюда[/url]. Полный модуль bas, включающий в себя еще несколько функций для работы с часовыми поясами можно скачать [url=http://www.cpearson.com/Zips/modTimeZones.zip]здесь[/url] или прямо отсюда: [attachment=1]modTimeZones.zip[/attachment]
Итак, приступим (для примера будем работать в MS Excel Visual Basic for Applications):
[list=1][*] Создаем в рабочей книге MS Excel модуль (если его еще нет)
[*] Вставляем в этот модуль [spoiler title=VBA код:][code]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
[/code][/spoiler]
[*] Пользуемся созданной нами функцией [b][i]LocalOffsetFromGMT()[/i][/b] в любом месте этой рабочей книги MS Excel (или вообще из любой рабочей книги MS Excel, если модуль сохранен в личной книге макросов). [/list]
[center][b][size=130]Пример:[/size][/b][/center]
Необходимо конвертировать дату и время (в формате Unix Datestamp) установки MS Windows, полученное из реестра [b][i]HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\InstallDate[/i][/b] и помещенное в ячейку «[b][i]A2[/i][/b]» в обычный удобочитаемый формат, при этом учесть часовой пояс системы.
О том, как конвертировать из Unix Datestamp в формат MS Excel читаем [url=http://manaeff.ru/forum/viewtopic.php?p=1431#p1431]здесь[/url].
Остается только добавить в формулу поправку на наш часовой пояс. Но, поскольку функция [b][i]LocalOffsetFromGMT()[/i][/b] возвращает значение в [b]минутах[/b], а расчет в формуле в ячейке ведется в днях, то мы должны конвертировать это значение в [b]дни[/b], для чего используем коэффициент [i]60*24=[b]1440[/b][/i].
Итак, окончательная формула в ячейке «[b][i]A4[/i][/b]» будет выглядеть так: [code]=A2/86400+LocalOffsetFromGMT()/1440+ДАТА(1970;1;1)[/code]
где: [list][*] [b][i]A2[/i][/b] - адрес ячейки с временем в формате Unix Timestamp
[*] [b][i]86400[/i][/b] - коэффициент, равный количеству секунд в одних сутках
[*] [b][i]ДАТА(1970;1;1)[/i] - дата 01 января 1970 года, с которой ведется отсчет Unix Timestamp[/b][/list]
[attachment=0]05.JPG[/attachment]