Como trabalhar com valores de data e hora¶
Os cálculos de data e hora estão entre os mais utilizados e mais críticos na análise e mineração de dados. Este tópico fornece exemplos práticos de consultas e cálculos comuns de data e hora.
Neste tópico:
Carregamento de datas e carimbos de data/hora¶
Carregamento de carimbos de data/hora sem fuso horário anexado¶
No exemplo a seguir, o parâmetro TIMESTAMP_TYPE_MAPPING é definido como TIMESTAMP_LTZ (fuso horário local). O parâmetro TIMEZONE está definido para a hora de América/Chicago. Se um conjunto de carimbos de data/hora não tem um fuso horário especificado, então o Snowflake carrega as cadeias de caracteres considerando que os carimbos de data/hora representam a hora local no fuso horário definido.
ALTER SESSION SET TIMESTAMP_TYPE_MAPPING = 'TIMESTAMP_LTZ';
ALTER SESSION SET TIMEZONE = 'America/Chicago';
CREATE OR REPLACE TABLE time (ltz TIMESTAMP);
INSERT INTO time VALUES ('2016-05-01 00:00:00.000');
SELECT * FROM time;
+---------------------------------+
| LTZ |
|---------------------------------|
| Sun, 01 May 2016 00:00:00 -0500 |
+---------------------------------+
Carregamento de carimbos de data/hora com fuso horário anexado¶
No exemplo a seguir, o parâmetro TIMESTAMP_TYPE_MAPPING é definido como TIMESTAMP_LTZ (fuso horário local). O parâmetro TIMEZONE está definido para a hora de América/Chicago. Suponha que um conjunto de carimbos de data/hora tenha um fuso horário diferente especificado. O Snowflake carrega a cadeia de caracteres na hora de América/Chicago.
ALTER SESSION SET TIMESTAMP_TYPE_MAPPING = 'TIMESTAMP_LTZ';
ALTER SESSION SET TIMEZONE = 'America/Chicago';
CREATE OR REPLACE TABLE time (ltz TIMESTAMP);
INSERT INTO time VALUES ('2016-04-30 19:00:00.000 -0800');
SELECT * FROM time;
+---------------------------------+
| LTZ |
|---------------------------------|
| Sat, 30 Apr 2016 22:00:00 -0500 |
+---------------------------------+
Conversão de carimbos de data/hora em fusos horários alternativos¶
No exemplo a seguir, um conjunto de valores de carimbo de data/hora é armazenado sem dados de fuso horário. Os carimbos de data/hora são carregados na hora UTC e convertidos para outros fusos horários:
ALTER SESSION SET TIMEZONE = 'UTC';
ALTER SESSION SET TIMESTAMP_LTZ_OUTPUT_FORMAT = 'YYYY-MM-DD HH24:MI:SS TZH:TZM';
CREATE OR REPLACE TABLE utctime (ntz TIMESTAMP_NTZ);
INSERT INTO utctime VALUES ('2016-05-01 00:00:00.000');
SELECT * FROM utctime;
SELECT CONVERT_TIMEZONE('UTC','America/Chicago', ntz)::timestamp_ltz AS ChicagoTime
FROM utctime;
SELECT CONVERT_TIMEZONE('UTC','America/Los_Angeles', ntz)::timestamp_ltz AS LATime
FROM utctime;
Inserção de cadeias de datas válidas em colunas de datas em uma tabela¶
Este exemplo mostra como inserir um valor em uma coluna DATE.
CREATE TABLE my_table(id INTEGER, date1 DATE); -- July 23, 2016. INSERT INTO my_table(id, date1) VALUES (1, TO_DATE('2016.07.23', 'YYYY.MM.DD')); -- NULL. INSERT INTO my_table(id) VALUES (2);SELECT id, date1 FROM my_table ORDER BY id; +----+------------+ | ID | DATE1 | |----+------------| | 1 | 2016-07-23 | | 2 | NULL | +----+------------+
A função TO_DATE aceita valores TIMESTAMP e até cadeias de caracteres no formato TIMESTAMP, mas descarta as informações de tempo (horas, minutos, etc.).
INSERT INTO my_table(id, date1) VALUES (3, TO_DATE('2020.02.20 11:15:00', 'YYYY.MM.DD HH:MI:SS')), (4, TO_TIMESTAMP('2020.02.24 04:00:00', 'YYYY.MM.DD HH:MI:SS'));SELECT id, date1 FROM my_table WHERE id >= 3; +----+------------+ | ID | DATE1 | |----+------------| | 3 | 2020-02-20 | | 4 | 2020-02-24 | +----+------------+
Se você inserir um DATE que foi definido com apenas uma hora, então a data padrão é 1 de janeiro, 1970.
INSERT INTO my_table(id, date1) VALUES (5, TO_DATE('11:20:30', 'hh:mi:ss'));SELECT id, date1 FROM my_table WHERE id = 5; +----+------------+ | ID | DATE1 | |----+------------| | 5 | 1970-01-01 | +----+------------+
Quando você recupera informações de DATE, pode formatá-las como um TIMESTAMP se desejar:
SELECT id, TO_VARCHAR(date1, 'dd-mon-yyyy hh:mi:ss') AS date1 FROM my_table ORDER BY id; +----+----------------------+ | ID | DATE1 | |----+----------------------| | 1 | 23-Jul-2016 00:00:00 | | 2 | NULL | | 3 | 20-Feb-2020 00:00:00 | | 4 | 24-Feb-2020 00:00:00 | | 5 | 01-Jan-1970 00:00:00 | +----+----------------------+
Recuperação da data e hora atuais¶
Obtenha a data atual como um valor DATE:
SELECT current_date();
Obtenha a data e hora atuais como um valor TIMESTAMP:
SELECT current_timestamp();
Recuperação de datas e dias da semana¶
Obtenha o dia atual da semana como um número usando a função EXTRACT:
SELECT EXTRACT('dayofweek',current_date());
Nota
A parte
dayofweek_iso
segue o padrão ISO-8601 de elementos de dados e formatos de intercâmbio. A função retorna o dia da semana como um valor inteiro na faixa 1-7, onde 1 representa a segunda-feira.Para compatibilidade com alguns outros sistemas, a parte
dayofweek
segue o padrão UNIX. A função retorna o dia da semana como um valor inteiro na faixa 0-6, onde 0 representa o domingo.
Obtenha o dia atual da semana como uma cadeia de caracteres usando a função TO_VARCHAR ou DECODE:
-- Output short English names, e.g. "Sun", "Mon" etc. SELECT TO_VARCHAR(current_date(), 'DY'); -- Output arbitrary, explicitly-provided weekday names: SELECT DECODE(EXTRACT ('dayofweek_iso',current_date()), 1, 'Monday', 2, 'Tuesday', 3, 'Wednesday', 4, 'Thursday', 5, 'Friday', 6, 'Saturday', 7, 'Sunday');
Recuperação de partes de data e hora¶
Obtenha várias partes de data e hora para a data e hora atual usando a função DATE_PART:
-- Current day of the month SELECT DATE_PART(day, current_timestamp()); -- Current year SELECT DATE_PART(year, current_timestamp()); -- Current month SELECT DATE_PART(month, current_timestamp()); -- Current hour SELECT DATE_PART(hour, current_timestamp()); -- Current minute SELECT DATE_PART(minute, current_timestamp()); -- Current second SELECT DATE_PART(second, current_timestamp());
Opção alternativa usando a função EXTRACT:
-- Current day of the month SELECT EXTRACT('day', current_timestamp()); -- Current year SELECT EXTRACT('year', current_timestamp()); -- Current month SELECT EXTRACT('month', current_timestamp()); -- Current hour SELECT EXTRACT('hour', current_timestamp()); -- Current minute SELECT EXTRACT('minute', current_timestamp()); -- Current second SELECT EXTRACT('second', current_timestamp());
Saída tabular alternativa:
SELECT day(current_timestamp() ) , hour( current_timestamp() ) , second(current_timestamp()) , minute(current_timestamp()) , month(current_timestamp()); +---------------------------+-----------------------------+-----------------------------+-----------------------------+----------------------------+ | DAY(CURRENT_TIMESTAMP() ) | HOUR( CURRENT_TIMESTAMP() ) | SECOND(CURRENT_TIMESTAMP()) | MINUTE(CURRENT_TIMESTAMP()) | MONTH(CURRENT_TIMESTAMP()) | |---------------------------+-----------------------------+-----------------------------+-----------------------------+----------------------------| | 7 | 6 | 43 | 44 | 9 | +---------------------------+-----------------------------+-----------------------------+-----------------------------+----------------------------+
Cálculo de datas e horas de calendários comerciais¶
Obtenha o primeiro dia do mês como um valor DATE usando a função DATE_TRUNC. Por exemplo, obtenha o primeiro dia do mês atual:
SELECT DATE_TRUNC('month', current_date());
Obtenha o último dia do mês atual como um valor DATE usando as funções DATEADD e DATE_TRUNC:
SELECT DATEADD('day',-1, DATE_TRUNC('month', DATEADD(day,31,DATE_TRUNC('month',current_date()) ) ) );
Opção alternativa. No exemplo a seguir, DATE_TRUNC recupera o início do mês atual, adiciona um mês para recuperar o início do mês seguinte e depois subtrai 1 dia para determinar o último dia do mês atual.
SELECT DATEADD('day', -1,
DATEADD('month', 1,
DATE_TRUNC('month', current_date())));
Obtenha o último dia do mês anterior como um valor DATE:
SELECT DATEADD(day, -1, DATE_TRUNC('month',current_date()) );
Obtenha o mês atual do ano pelo nome:
-- Output short English names, e.g. "Jan", "Dec", etc.
SELECT TO_VARCHAR(current_date(), 'Mon');
-- Output arbitrary, explicitly-provided month names
SELECT DECODE(EXTRACT('month',current_date()),
1, 'January',
2, 'February',
3, 'March',
4, 'April',
5, 'May',
6, 'June',
7, 'July',
8, 'August',
9, 'September',
10, 'October',
11, 'November',
12, 'December');
Obtenha a data para segunda-feira da semana atual:
SELECT DATEADD('day', (EXTRACT('dayofweek_iso', current_date()) * -1) +1 , current_date() );
Obtenha a data para sexta-feira da semana atual:
SELECT DATEADD('day', (5 - EXTRACT('dayofweek_iso', current_date()) ) , current_date() );
Obtenha a data para a primeira segunda-feira do mês atual usando a função DATE_PART:
SELECT DATEADD(
day,
MOD( 7 + 1 - DATE_PART('dayofweek_iso', DATE_TRUNC('month', current_date()) ), 7),
DATE_TRUNC('month', current_date()));
Nota
Na consulta acima, o valor 1
em 7 + 1
é convertido em segunda-feira. Para recuperar a data da primeira terça-feira, quarta-feira, etc., substitua 2
, 3
e assim por diante, respectivamente, até 7
por Sunday
.
Obtenha o primeiro dia do ano atual como um valor DATE:
SELECT DATE_TRUNC('year', current_date());
Obtenha o último dia do ano atual como um valor DATE:
SELECT DATEADD('day', -1,
DATEADD('year', 1,
DATE_TRUNC('year', current_date())));
Obtenha o último dia do ano anterior como um valor DATE:
SELECT DATEADD('day', -1, DATE_TRUNC('year',current_date()) );
Obtenha o primeiro dia do trimestre atual como um valor DATE:
SELECT DATE_TRUNC('quarter',current_date());
Obtenha o último dia do trimestre atual como um valor DATE:
SELECT DATEADD('day', -1,
DATEADD('month', 3,
DATE_TRUNC('quarter', current_date())));
Obtenha a data e o carimbo de data/hora para a meia-noite do dia atual:
SELECT DATE_TRUNC('day', current_timestamp());
+----------------------------------------+
| DATE_TRUNC('DAY', CURRENT_TIMESTAMP()) |
|----------------------------------------|
| Wed, 07 Sep 2016 00:00:00 -0700 |
+----------------------------------------+
Incremento de valores de data e hora¶
Adicione dois anos à data atual:
SELECT DATEADD(year, 2, current_date());
Adicione dois dias à data atual:
SELECT DATEADD(day,2,current_date());
Adicione duas horas à data e hora atuais:
SELECT DATEADD(hour,2,current_timestamp());
Adicione dois minutos à data e hora atuais:
SELECT DATEADD(minute,2,current_timestamp());
Adicione dois segundos à data e hora atuais:
SELECT DATEADD(second,2,current_timestamp());
Conversão de cadeias de caracteres válidas em datas, horários ou carimbos de data/hora¶
Na maioria dos casos de uso, o Snowflake manipula corretamente os valores de data e carimbo de data/hora formatados como cadeias de caracteres. Em certos casos, tais como comparações baseadas em cadeia de caracteres ou quando um resultado depende de um formato de carimbo de data/hora diferente do definido nos parâmetros da sessão, recomendamos explicitamente a conversão de valores para o formato desejado para evitar resultados inesperados.
Por exemplo, sem conversão explícita, a comparação dos valores das cadeias de caracteres produz resultados baseados em cadeias de caracteres:
-- Note the column data type is string
CREATE OR REPLACE TABLE timestamps(timestamp1 string);
INSERT INTO timestamps VALUES
('Fri, 05 Apr 2013 00:00:00 -0700'),
('Sat, 06 Apr 2013 00:00:00 -0700'),
('Sat, 01 Jan 2000 00:00:00 -0800'),
('Wed, 01 Jan 2020 00:00:00 -0800');
-- Comparison without explicit casting
SELECT * FROM timestamps WHERE timestamp1 < '2014-01-01';
+------------+
| TIMESTAMP1 |
|------------|
+------------+
-- Comparison with explicit casting to date
SELECT * FROM timestamps WHERE timestamp1 < '2014-01-01'::date;
+---------------------------------+
| DATE1 |
|---------------------------------|
| Fri, 05 Apr 2013 00:00:00 -0700 |
| Sat, 06 Apr 2013 00:00:00 -0700 |
| Sat, 01 Jan 2000 00:00:00 -0800 |
+---------------------------------+
Para obter mais informações sobre funções de conversão, consulte Formatos de data e hora em funções de conversão.
Aplicação de aritmética de data a cadeias de caracteres de data¶
Adicione cinco dias à data expressa em uma cadeia de caracteres:
SELECT DATEADD('day',5,TO_TIMESTAMP ('12-jan-2016 00:00:00','dd-mon-yyyy hh:mi:ss') );
+--------------------------------------------------------------------------------+
| DATEADD('DAY',5,TO_TIMESTAMP ('12-JAN-2016 00:00:00','DD-MON-YYYY HH:MI:SS') ) |
|--------------------------------------------------------------------------------|
| Thu, 17 Jan 2016 00:00:00 -0800 |
+--------------------------------------------------------------------------------+
Calcule a diferença em dias entre a data atual e a data expressa em uma cadeia de caracteres usando a função DATEDIFF:
-- Using the TO_TIMESTAMP function:
SELECT DATEDIFF('day', TO_TIMESTAMP ('12-jan-2016 00:00:00','dd-mon-yyyy hh:mi:ss') , current_date() );
+-------------------------------------------------------------------------------------------------+
| DATEDIFF('DAY', TO_TIMESTAMP ('12-JAN-2016 00:00:00','DD-MON-YYYY HH:MI:SS') , CURRENT_DATE() ) |
|-------------------------------------------------------------------------------------------------|
| 240 |
+-------------------------------------------------------------------------------------------------+
-- Using the TO_DATE function:
SELECT DATEDIFF('day', TO_DATE ('12-jan-2016 00:00:00','dd-mon-yyyy hh:mi:ss'), current_date() );
+-------------------------------------------------------------------------------------------+
| DATEDIFF('DAY', TO_DATE ('12-JAN-2016 00:00:00','DD-MON-YYYY HH:MI:SS'), CURRENT_DATE() ) |
|-------------------------------------------------------------------------------------------|
| 240 |
+-------------------------------------------------------------------------------------------+
Adicione um dia a uma data especificada:
SELECT TO_DATE('2019-01-15') + 1;
+---------------------------+
| TO_DATE('2019-01-15') + 1 |
|---------------------------|
| 2019-01-16 |
+---------------------------+
Subtraia 9 dias da data atual (por exemplo, 21 Jan, 2019):
SELECT CURRENT_DATE() - 9;
+--------------------+
| CURRENT_DATE() - 9 |
|--------------------|
| 2019-01-12 |
+--------------------+
Cálculo de diferenças entre datas ou horas¶
Calcule a diferença entre a data atual e a data em três anos:
SELECT DATEDIFF(year, current_date(),
DATEADD(year, 3, current_date() ) );
Calcule a diferença entre a data atual e a data em três meses:
SELECT DATEDIFF(month, current_date(),
DATEADD(month, 3, current_date()) );
Calcule a diferença entre a data atual e a data em três dias:
SELECT DATEDIFF(day, current_date(),
DATEADD(day, 3, current_date()) );
Calcule a diferença entre a hora atual e a hora em três horas:
SELECT DATEDIFF(hour, current_timestamp(),
DATEADD(hour, 3, current_timestamp()) );
Calcule a diferença entre a hora atual e a hora em três minutos:
SELECT DATEDIFF(minute, current_timestamp(),
DATEADD(minute, 3, current_timestamp()) );
Calcule a diferença entre a hora atual e a hora em três segundos:
SELECT DATEDIFF(second, current_timestamp(),
DATEADD(second, 3, current_timestamp()) );
Criação de exibições de calendário anuais¶
CREATE OR REPLACE VIEW
calendar_2016 as SELECT n, theDate,
DECODE (EXTRACT('dayofweek',theDate),
1 , 'Monday',
2 , 'Tuesday',
3 , 'Wednesday',
4 , 'Thursday',
5 , 'Friday',
6 , 'Saturday',
0 , 'Sunday'
) theDayOfTheWeek,
DECODE (EXTRACT(month FROM theDate),
1 , 'January',
2 , 'February',
3 , 'March',
4 , 'April',
5 , 'May',
6 , 'June',
7 , 'July',
8 , 'August',
9 , 'september',
10, 'October',
11, 'November',
12, 'December'
) theMonth,
EXTRACT(year from theDate) theYear
FROM
(SELECT
row_number() OVER (order by seq4()) AS n,
DATEADD(day, row_number() OVER (order by seq4())-1, TO_DATE('2016-01-01'))
AS theDate
FROM table(generator(rowCount => 365))) ORDER BY n ASC;
SELECT * from CALENDAR_2016;
+-----+------------+-----------------+-----------+---------+
| N | THEDATE | THEDAYOFTHEWEEK | THEMONTH | THEYEAR |
|-----+------------+-----------------+-----------+---------|
| 1 | 2016-01-01 | Friday | January | 2016 |
| 2 | 2016-01-02 | Saturday | January | 2016 |
...
| 364 | 2016-12-29 | Thursday | December | 2016 |
| 365 | 2016-12-30 | Friday | December | 2016 |
+-----+------------+-----------------+-----------+---------+