Фильтровать даты на основе часового пояса Кувейта в SQL Server

#sql #sql-server #datetime #timezone #timezone-offset

#sql #sql-сервер #дата-время #Часовой пояс #смещение часового пояса

Вопрос:

У меня есть следующий запрос, который направлен на вычисление пользовательских депозитов с последнего (предыдущего) Суббота с 00:00:00 до конца дня (воскресенье 00:00:00)

Мой столбец даты (плохо называемый ‘datetime’) не содержит никаких сведений о часовом поясе (пример: 2020-09-11 21:52:37.803). Тем не менее, он основан на часовом поясе Латвии / Риги, где расположен мой сервер.

При фильтрации моих строк на основе datetime между 00:00:00 субботы и 00:00:00 воскресенья я не принимаю во внимание тот факт, что мне не нужно фильтровать эту дату по латвийскому времени (время сервера), а по другому времени, которое является «арабским стандартным часовым поясом», в котором находятся мои клиенты.

На сегодняшний день часовой пояс моего столбца даты SQL и арабский часовой пояс равны (UTC 3), но зимой время между зонами будет отличаться.

Как я могу справиться с потенциальной разницей во времени между этими 2 часовыми поясами и быть уверенным, что, несмотря на латвийское время, я всегда фильтрую на основе субботы 00:00:00 и воскресенья 00:00:00 по кувейтскому времени? Должен ли я использовать AT TIME_ZONE или смещать datetime, чтобы отразить час арабского часового пояса?

  SELECT 
      UserID, 
      SUM (DEPOSIT) AS deposits 
    FROM 
      (
        SELECT 
          UserID, 
          datetime, 
          CASE WHEN TranType = 'DEPOSIT' THEN AmountReal ELSE 0 END AS DEPOSIT 
        FROM 
          DataFeed 
        WHERE 
          datetime >= CAST (
            CAST (
              IIF (
                0 = DATEPART(
                  dw, 
                  GETDATE()
                ), 
                GETDATE(), 
                DATEADD(
                  d, 
                  (
                    (
                      (
                        7   0 - DATEPART(
                          dw, 
                          GETDATE()
                        )
                      ) % 7
                    ) -7
                  ), 
                  GETDATE()
                )
              ) AS DATE
            ) AS datetime
          ) --last saturday at 00:00 0=saturday
          AND datetime <= CAST (
            CAST (
              IIF (
                1 = DATEPART(
                  dw, 
                  GETDATE()
                ), 
                GETDATE(), 
                DATEADD(
                  d, 
                  (
                    (
                      (
                        7   1 - DATEPART(
                          dw, 
                          GETDATE()
                        )
                      ) % 7
                    ) -7
                  ), 
                  GETDATE()
                )
              ) AS DATE
            ) AS datetime
          ) 
      ) alltrans 
    GROUP BY 
      UserID
  

Ответ №1:

Я бы посоветовал вам хранить данные в UTC. Таким образом, у вас не будет проблем независимо от часового пояса.

Преобразовать существующие временные метки в UTC. Поскольку вы знаете, что время указано в часовом поясе Латвии, вы можете легко выполнить преобразование и сохранить в UTC. Выполняйте все ваши запросы в будущем, преобразуя время UTC в соответствующий арабский часовой пояс, в котором проживают ваши клиенты. DateTimeOffset тип данных не учитывает летнее время. Вам необходимо соответствующим образом обработать его в зимнее время, чтобы применить соответствующее смещение при преобразовании даты и времени.

Вы можете использовать TODATETIMEOFFSET для применения преобразования из UTC.

 DECLARE @todaysDateTime datetime2;  
SET @todaysDateTime = GETUTCDATE()
SELECT TODATETIMEOFFSET (@todaysDateTime, ' 03:00');  
  

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

1. Я не могу хранить данные по-другому, поскольку я должен управлять ими как пользователь, доступный только для чтения

2. Si при любом преобразовании времени это должно выполняться на лету

3. @R_life_R,Поскольку данные хранятся в часовом поясе Латвии. Я бы посоветовал вам преобразовать входящие данные в соответствующий часовой пояс, а затем выполнить запросы к данным. Я понимаю, что данные доступны только для чтения. Итак, вы должны обработать это в своем запросе.