Могу ли я конвертировать часовые пояса в SQL Server? - PullRequest
4 голосов
/ 07 июля 2010

Прямо сейчас я храню несколько записей в SQL Server со столбцом DATETIME, в котором хранится текущая временная метка с использованием GETUTCDATE().Это гарантирует, что мы всегда храним точную дату, не беспокоясь о таких вопросах, как «ну это 2:00 моего или 2:00 вашего времени?»Использование UTC гарантирует, что мы точно знаем, когда это произошло, независимо от часового пояса.

Однако у меня есть запрос, который по существу группирует эти записи по дате.Упрощенная версия этого запроса выглядит примерно так:

SELECT [created], SUM([amount]) AS [amount]
FROM (
    SELECT [amount], LEFT(CONVERT(VARCHAR, [created], 120), 10) AS [created]
    FROM (
        SELECT [amount], DATEADD(HOUR, -5, [created]) AS [created]
        FROM [sales]
        WHERE [organization] = 1
    ) AS s
) AS s
GROUP BY [created]
ORDER BY [created] ASC

Очевидно, что этот запрос далеко не идеален - единственная причина, по которой я здесь, состоит в том, чтобы спросить, как его улучшить.Во-первых, он (по большей части) выполняет цель, которую я здесь ищу, - это вещи, сгруппированные по датам, и другие значения, сгруппированные соответственно.Но то, чего он не достигает, - это корректное обращение с летним временем.

Я живу в Мэдисоне, штат Висконсин, и у нас центральное время, поэтому с марта по ноябрь мы UTC-5, иначе мы "по UTC-6.Вот почему вы видите -5 в коде как быстрый взлом, чтобы заставить его работать.

Проблема в том, что, если я запускаю этот запрос, и есть записи, которые попадают с обеих сторон перехода на летнее времяизменение времени может потенциально сгруппировать вещи неправильно.Так, например, если таблица выглядит примерно так:

+----+--------+---------------------+
| id | amount | created             |
+----+--------+---------------------+
|  1 | 100.00 | 2010-04-02 06:00:00 |
|  2 |  50.00 | 2010-04-02 04:30:00 |
|  3 |  75.00 | 2010-04-02 03:00:00 |
|  4 | 150.00 | 2010-03-02 07:00:00 |
|  5 |  25.00 | 2010-03-02 05:30:00 |
|  6 |  50.00 | 2010-03-02 04:00:00 |
+----+--------+---------------------+

Мой запрос вернет это:

+------------+--------+
| created    | amount |
+------------+--------+
| 2010-03-01 |  50.00 |
| 2010-03-02 | 175.00 |
| 2010-04-01 | 125.00 |
| 2010-04-02 | 100.00 |
+------------+--------+

Однако, в идеале, СЛЕДУЕТ возвращать это:

+------------+--------+
| created    | amount |
+------------+--------+
| 2010-03-01 |  75.00 |
| 2010-03-02 | 150.00 |
| 2010-04-01 | 125.00 |
| 2010-04-02 | 100.00 |
+------------+--------+

Проблема в том, что если я просто вычитаю фиксированное -5, то апрель верен, а март - нет, но если я вместо этого вычту фиксированное -6, то март верен, а апрель - нет.Что мне действительно нужно сделать, так это конвертировать в соответствующий часовой пояс таким образом, чтобы он учитывал переход на летнее время и мог соответственно отрегулироваться.Могу ли я сделать это с помощью SQL-запроса?Как мне написать этот запрос?

Ответы [ 2 ]

2 голосов
/ 07 июля 2010

Ни одна из функций текущей даты / времени не поддерживает DST.

Лучше всего использовать вспомогательную таблицу календаря:

http://web.archive.org/web/20070611150639/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html

Вы можете сохранитьUTCOffset по дате и ссылки на него в выбранной выписке

1 голос
/ 09 июля 2010

Если вы смогли сохранить ваши данные в поле datetimeoffset вместо datetime это может помочь.

http://msdn.microsoft.com/en-us/library/bb630289.aspx

Этот тип данных и функции corepsonding являются новой функцией SQL Server 2008.

...