Существует ли какая-либо эквивалентная функция CURRENT_TIMEZONE_ID в SQL Server

#sql #sql-server #tsql #timezone

#sql #sql-server #tsql #Часовой пояс

Вопрос:

Существует ли какая-либо эквивалентная функция CURRENT_TIMEZONE_ID в SQL Server?

Существует уродливый способ считывания текущего идентификатора часового пояса в SQL Server путем чтения раздела реестра следующим образом

введите описание изображения здесь

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

И я не смог найти никакого прямого способа или функции, подобной этому CURRENT_TIMEZONE_ID для SQL Server.

Есть ли она?

Ответ №1:

Взгляните на

 select Sysdatetimeoffset()
  

Это дает смещение часового пояса сервера по отношению к UTC.

Небольшое примечание, возможно, сделайте так, чтобы хранить все даты как UTC, таким образом, вы в SQL, а также разработчики могут легко обрабатывать дату и преобразовывать ее в локальные даты, поскольку нет никаких предположений, были ли данные введены сервером на сервере, стоящем в Азии или в США. По умолчанию для серверного времени используется GetDate(), то же самое для UTC — GetUtcDate(), что не так уж сложно сделать…

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

 DECLARE @TimeZone VARCHAR(50)
EXEC MASTER.dbo.xp_regread 'HKEY_LOCAL_MACHINE',
'SYSTEMCurrentControlSetControlTimeZoneInformation',
'TimeZoneKeyName',@TimeZone OUT
SELECT @TimeZone
  

введите описание изображения здесь

Обновление на основе вашего ответа

Как упоминалось выше., вы можете использовать Sysdatetimeoffset(), если вы не знаете, что LAT / LONG или можете использовать.Net и созданное расширенное свойство — единственный способ TSQL получить приблизительное значение, получив смещение и сопоставив его с именами часовых поясов в SQL server.

Вот 2 примера, первый принимает смещение часового пояса и помещает его в переменную, затем запрашивает таблицу с переменной offset

 declare @offset sysname
SELECT top(1) @offset = value 
from String_Split(cast(Sysdatetimeoffset() as varchar(50)),' ')
order by value;

SELECT [name] FROM sys.time_zone_info where [current_utc_offset]= @offset;
  

или используйте подзапрос, в основном два способа сделать то же самое

 SELECT [name] FROM sys.time_zone_info 
where [current_utc_offset] in ( SELECT top(1) value 
from String_Split(cast(Sysdatetimeoffset() as varchar(50)),' ')
order by value)
  

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

Вы могли бы сделать это с помощью относительно небольшого количества строк кода:

 using System;
using System.Data.SqlTypes;

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction(DataAccess = Microsoft.SqlServer.Server.DataAccessKind.None
        ,IsDeterministic =true
        ,SystemDataAccess = Microsoft.SqlServer.Server.SystemDataAccessKind.None
        ,Name = "TimeZoneName"
        
        )]
    public static SqlString TimeZoneName()
    {
        return new SqlString(TimeZone.CurrentTimeZone.StandardName);
    }
}
  

Хороший пример для создания, развертывания и т. Д. Здесь https://sqlclr-tutorial.net/en/tutorial/100006/clr-user-defined-functions

Поскольку вы не получаете доступ к объектам в SQL и не выполняете или не получаете внешний доступ, все экземпляры SQL могут разрешить это, поскольку это безопасный код

Комментарии:

1. Мое требование — получить идентификатор часового пояса конкретно. В своем вопросе я упомянул, что я не хочу читать реестр, потому что решение, которое вы опубликовали, я уже знаю. Но я не хочу использовать это решение.

2. @PawanNogariya, каким-то образом я, должно быть, пропустил ссылку на реестр, я обновил ответ, это помогает?

3. Спасибо! Но запросы не будут работать, потому что смещение часов может быть одинаковым для двух разных часовых поясов, поэтому ваши запросы будут возвращать более одного часового пояса, и нет способа узнать, какой из них является текущим. Например US Eastern Standard Time , и Turks And Caicos Standard Time имеет тот же часовой -5 пояс, поэтому для -5 двух записей будут приходить, и вы никогда не узнаете, какая из них текущая

4. @PawanNogariya, это то, что я написал, теперь у вас осталась среда CLR