{"id":562,"date":"2015-03-14T16:17:20","date_gmt":"2015-03-14T19:17:20","guid":{"rendered":"http:\/\/thesqltimes.com\/blog\/?p=562"},"modified":"2018-12-19T20:32:17","modified_gmt":"2018-12-19T23:32:17","slug":"sql-datas-parte1","status":"publish","type":"post","link":"https:\/\/thesqltimes.com\/blog\/2015\/03\/14\/sql-datas-parte1\/","title":{"rendered":"1. SQL Server, Datas e Horas"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"Muito \u00fatil!\" data-post-id=\"562\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div><div class=\"seriesmeta\">Post 1\/3. Este post \u00e9 parte da s\u00e9rie: <a href=\"https:\/\/thesqltimes.com\/blog\/series\/sql-datas-basico\/\" class=\"series-124\" title=\"SQL Server: Esclarecendo Datas e Horas\">SQL Server: Esclarecendo Datas e Horas<\/a>\r\n<\/div>\r\n<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Tempo de Leitura:<\/span> <span class=\"rt-time\"> 8<\/span> <span class=\"rt-label rt-postfix\">minutos<\/span><\/span><p>Tempo \u00e9 uma coisa interessante. Dias, anos, horas, minutos, milissegundos&#8230; Em algum momento de sua vida com banco de dados voc\u00ea precisou, ou vai precisar, trabalhar com tempo. Datas e horas nos permitem realizar m\u00e9tricas, organizar compromissos, etc., e a maioria dos sistemas hoje em dia\u00a0necessitam manipular data e hora.<\/p>\n<p>O SQL Server fornece um amplo suporte para que voc\u00ea possa n\u00e3o s\u00f3 armazenar, mas realizar diversas opera\u00e7\u00f5es como somar, ou subtrair,\u00a0horas, dias, segundos, anos, ordenar e comparar data e hora! Por\u00e9m, existe uma s\u00e9rie de mitos e confus\u00f5es relacionados a\u00a0este assunto. Por exemplo, voc\u00ea \u00e9 capaz de explicar o porqu\u00ea isso acontece?<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"Arrendondamento de Datetime\">SELECT\r\n\tR.DataString\r\n\t,CONVERT(datetime,R.DataString) as DataDatetime\r\nFROM\r\n\t(\r\n\t\tSELECT '20150314 23:59:59.999' as DataString\r\n\t\tUNION ALL\r\n\t\tSELECT '20150314 12:00:00.005'\r\n\t\r\n\t) R<\/pre>\n<figure id=\"attachment_601\" aria-describedby=\"caption-attachment-601\" style=\"width: 313px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-601 size-full\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/resultset_arredondamento_datetime-e1426347367627.png\" alt=\"Ao converter uma string para data, o SQL n\u00e3o apresentou o mesmo hor\u00e1rio\" width=\"313\" height=\"66\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/resultset_arredondamento_datetime-e1426347367627.png 313w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/resultset_arredondamento_datetime-e1426347367627-300x63.png 300w\" sizes=\"auto, (max-width: 313px) 100vw, 313px\" \/><figcaption id=\"caption-attachment-601\" class=\"wp-caption-text\">Ao converter uma string para data, o SQL n\u00e3o apresentou o mesmo hor\u00e1rio<\/figcaption><\/figure>\n<p>O objetivo deste post \u00e9 esclarecer como manipular datas dentro de seus scripts T-SQL. \u00a0Iremos abordar os seguintes assuntos:<\/p>\n<ol>\n<li><strong>Representando datas<\/strong><\/li>\n<li><strong>Formatando a exibi\u00e7\u00e3o<\/strong><\/li>\n<li><strong>Tipos de dados de data<\/strong><\/li>\n<\/ol>\n<p>Por hoje, vamos focar na representa\u00e7\u00e3o das datas, isto \u00e9, o modo como o SQL Server entende\u00a0as datas que enviamos para ele.<\/p>\n<h3><strong>Formato de Datas<\/strong><\/h3>\n<p>Vamos come\u00e7ar falando do formato. Existe uma enorme confus\u00e3o neste assunto. Primeiro, vamos deixar uma coisa bem clara:\u00a0existem as datas que sua aplica\u00e7\u00e3o envia para o SQL Server, via c\u00f3digo T-SQL, e as datas que o SQL Server envia para a sua aplica\u00e7\u00e3o. S\u00e3o duas coisas diferentes.<\/p>\n<h3><strong>Fornecendo Datas para o SQL Server<\/strong><\/h3>\n<p>Quando voc\u00ea envia um c\u00f3digo T-SQL para o SQL Server, quem na verdade envia \u00e9 uma aplica\u00e7\u00e3o. A aplica\u00e7\u00e3o \u00e9 o que chamamos de <em><strong>client <\/strong><\/em>(por conta da arquitetura client-server). \u00a0Tudo que um client faz \u00e9 pegar um c\u00f3digo T-SQL, que n\u00e3o passa de texto (string), entregar ao SQL Server para ele processar, e esperar a resposta. Quando o client precisa fornecer uma data ao SQL Server ela vai junto com o c\u00f3digo TSQL, como texto puro tamb\u00e9m.<\/p>\n<p>Esta data que vai no c\u00f3digo \u00e9 o que podemos chamar de &#8220;<strong><em>formato de entrada<\/em><\/strong>&#8220;.\u00a0Especificar uma data no SQL Server \u00e9 muito simples: basta colocar a bendita\u00a0entre aspas simples (&#8216;). Isso mesmo jovem, voc\u00ea especifica datas igual especifica uma string qualquer dentro da linguagem T-SQL. O SQL Server s\u00f3 vai entender que aquilo \u00e9\u00a0uma data, e n\u00e3o uma string qualquer, se ela for convertida para um tipo de dados de data, como por exemplo <em><strong>datetime<\/strong><\/em>,\u00a0<em><strong>time<\/strong><\/em>,\u00a0<em><strong>date<\/strong><\/em>,\u00a0<em><strong>datetime2<\/strong><\/em>, etc. Essa convers\u00e3o pode ser expl\u00edcita ou impl\u00edcita:<\/p>\n<ul>\n<li>Impl\u00edcitas\n<ul>\n<li>Quando atribui para uma vari\u00e1vel do tipo data\n<pre class=\"lang:tsql decode:true\" title=\"Impl\u00edcita: Atribui\u00e7\u00e3o de vari\u00e1vel\">DECLARE \r\n\t@MinhaData datetime\r\n;\r\n\r\nSET @MinhaData = '20140101' --&gt; Neste momento a string '20140101' ser\u00e1 convertida para um formato de data e salvo na vari\u00e1vel.\r\n\r\n--&gt; Perceba a diferen\u00e7a na exibi\u00e7\u00e3o. \r\nSELECT '20140101' DataString, @MinhaData as DataDatetme<\/pre>\n<\/li>\n<li>Quando atribui para uma coluna do tipo data\n<pre class=\"lang:tsql decode:true\" title=\"Impl\u00edcita: Atribui\u00e7\u00e3o de Coluna\">-- Uma tabela simples\r\nCREATE TABLE cadastro( nome varchar(100), dataAniversario datetime );\r\n\r\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t| Aqui \u00e9 uma string. Mas ao inserir na coluna dataAniversario, ela ser\u00e1 convertida para data.\r\nINSERT INTO cadastro(nome,dataAniversario) VALUES('Rodrigo','08\/03\/1992');\r\n\r\nSELECT * FROM cadastro;\r\n\t\t\t\t\t\t\t\t\t\r\nUPDATE cadastro SET dataAniversario = '650311' WHERE nome = 'Rodrigo'\r\n--\t\t\t\t\t\t\t\t\t|Aqui vai acontecer a convers\u00e3o impl\u00edtica de novo, quando o SQL atualizar a coluna.\r\n\r\n\r\nSELECT * FROM cadastro;<\/pre>\n<\/li>\n<li>Quando compara com alguma express\u00e3o do tipo data\n<pre class=\"lang:tsql decode:true\" title=\"Impl\u00edcita: Compara\u00e7\u00e3o de String com Data\">-- Uma tabela simples\r\nCREATE TABLE cadastro( nome varchar(100), dataAniversario datetime );\r\n\r\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t| Aqui \u00e9 uma string. Mas ao inserir na coluna dataAniversario, ela ser\u00e1 convertida para data.\r\nINSERT INTO cadastro(nome,dataAniversario) VALUES('Rodrigo','08\/03\/1992');\r\nINSERT INTO cadastro(nome,dataAniversario) VALUES('Tha\u00eds','01\/01\/1993');\r\nINSERT INTO cadastro(nome,dataAniversario) VALUES('Gustavo','09\/12\/2015');\r\nINSERT INTO cadastro(nome,dataAniversario) VALUES('Lucas','07\/07\/1965');\r\n\r\n--\t\t\t\t\t\t\t\t\t\t\t\t--&gt; Neste ponto, de novo, uma convers\u00e3o impl\u00edtica ser\u00e1 feita da string para data, para que a compara\u00e7\u00e3o possa ser feita!\r\nSELECT * FROM cadastro WHERE dataAniversario &gt;= '19930101'<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li>Expl\u00edcitas\n<ul>\n<li>Quando\u00a0converte usando CAST ou CONVERT para um tipo de data\n<pre class=\"lang:tsql decode:true\" title=\"Convers\u00e3o Expl\u00edcita\">SELECT\r\n\tCONVERT(datetime,'20140101')\r\n\t,CONVERT(datetime,'19920101 13:00')\r\n\t,CAST('20160101' as datetime)\r\n<\/pre>\n<p>&nbsp;<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Apesar do SQL Server parecer bem flex\u00edvel quanto ao formato de entrada, voc\u00ea n\u00e3o pode colocar qualquer coisa. N\u00e3o \u00e9 a casa da m\u00e3e Joana n\u00e3o! Ao converter sua string para uma data, o SQL Server vai validar o formato e se n\u00e3o estiver em conformidade\u00a0voc\u00ea ir\u00e1\u00a0receber um erro dizendo que n\u00e3o foi poss\u00edvel converter uma data a partir de uma string.<\/p>\n<figure id=\"attachment_623\" aria-describedby=\"caption-attachment-623\" style=\"width: 548px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-623\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/error_convert_Data.png\" alt=\"SQL Server Error 241\" width=\"548\" height=\"84\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/error_convert_Data.png 548w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/error_convert_Data-300x46.png 300w\" sizes=\"auto, (max-width: 548px) 100vw, 548px\" \/><figcaption id=\"caption-attachment-623\" class=\"wp-caption-text\">Este \u00e9 o erro que voc\u00ea ir\u00e1 ver com mais frequ\u00eancia quando estiver trabalhando com datas e o formato estiver errado.<\/figcaption><\/figure>\n<p>Essa string que cont\u00e9m uma data, que voc\u00ea coloca no c\u00f3digo SQL, \u00e9\u00a0chamada\u00a0de Literal (ou constante) de data e pode ser interpretado de v\u00e1rias formas.\u00a0 <a title=\"Books Online SQL Server - datetime\" href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms187819(v=sql.120).aspx\">Aqui na documenta\u00e7\u00e3o<\/a> voc\u00ea tem todos os detalhes.\u00a0O formato mais comum\u00a0de um literal de data no SQL Server \u00e9:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-610 aligncenter\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/general_date_literal-1024x298.png\" alt=\"Formato Geral de Literal de Datas\" width=\"756\" height=\"220\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/general_date_literal-1024x298.png 1024w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/general_date_literal-300x87.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/general_date_literal.png 1939w\" sizes=\"auto, (max-width: 756px) 100vw, 756px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>A primeira coisa \u00e9 entender os separadores. Basicamente, uma\u00a0data \u00e9 composta de v\u00e1rias partes: dia, m\u00eas, ano, hora, minutos, segundos e milissegundos. O SQL Server suporta barra (\/), o ponto (.) e o tra\u00e7o como separadores para a parte dos dias. Para a parte das horas somente os <strong>dois-pontos (:)<\/strong>\u00a0podem\u00a0ser usados para separar horas, minutos e segundos. E somente o ponto pode ser usado para separar milissegundos. Todas as datas a seguir s\u00e3o v\u00e1lidas:<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"Datas e Separadores\">SELECT\r\n\tCONVERT(datetime,'02\/02\/2010')\r\n\t,CONVERT(datetime,'02.02.2010')\r\n\t,CONVERT(datetime,'02-02-2010')\r\n\t,CONVERT(datetime,'02-02-2010 12:23:45.010')<\/pre>\n<p>Se voc\u00ea especificar um separador diferente destes mencionados acima, \u00a0vai dar erro&#8230;<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"Separadores Inv\u00e1lidos\">SELECT CONVERT(datetime,'02 02 2010')\r\nGO\r\nSELECT CONVERT(datetime,'02\/02\/2010 13.12.15.999')\r\nGO<\/pre>\n<p><span style=\"color: #ff0000;\">Msg 241, Level 16, State 1, Line 1<\/span><br \/>\n<span style=\"color: #ff0000;\">Conversion failed when converting date and\/or time from character string.<\/span><br \/>\n<span style=\"color: #ff0000;\">Msg 242, Level 16, State 3, Line 1<\/span><br \/>\n<span style=\"color: #ff0000;\">The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.<\/span><\/p>\n<p>Voc\u00ea pode omitir certas partes da data. Quando faz isso, o SQL Server considera a parte omitida como 0 (zero). \u00a0Se omitir a parte das\u00a0horas, isto \u00e9, especificar somente dia, m\u00eas e ano, o hor\u00e1rio ser\u00e1 o mesmo que 00:00:00.000, isto \u00e9, meia noite em ponto! O hor\u00e1rio tem de ser especificado no formato &#8220;<em>HH:mm:SS.Milissegundos [AM|PM]<\/em>&#8220;. Veja alguns exemplos:<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"Formatos de Hora\">SELECT \r\n\tCONVERT(datetime,'01\/01\/2015 00:00:00.000')  --&gt; V\u00e1lido! Mesma coisa quando especifica somente a data\r\n\t,CONVERT(datetime,'01\/01\/2015 00:01:00.500') --&gt; V\u00e1lido\r\n\t,CONVERT(datetime,'01\/01\/2015 00:00:00') --&gt; V\u00e1lido. Voc\u00ea pode omitir os segundos e millisegundos. O SQL ir\u00e1 considerar como sendo 0.\r\n\t,CONVERT(datetime,'01\/01\/2015 13:57') --&gt; V\u00e1lido! Isso \u00e9 o mesmo que 01\/01\/2015 13:57:00.000\r\nGO<\/pre>\n<p>O tipo &#8220;<em><strong>datetime<\/strong><\/em>&#8221; permite que voc\u00ea especifique at\u00e9 3 casas nos milissegundos. Os tipos <strong><em>time<\/em><\/strong> e <strong><em>datetime2<\/em><\/strong> permitem at\u00e9 7 casas! Depois falamos mais\u00a0sobre os diferentes tipos de dados de data e hora. Por agora, concentre-se no formato. Outra \u00a0coisa interessante \u00e9 que voc\u00ea pode especificar o formato 12 horas (AM\/PM) nas horas!<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"Formato 12 e 24 horas\">SELECT \r\n\tCONVERT(datetime,'01\/01\/2015 01:00AM') --&gt; 1 da manh\u00e3\r\n\t,CONVERT(datetime,'01\/01\/2015 01:00PM') --&gt; 1 da tarde\r\n\t,CONVERT(datetime,'01\/01\/2015 13:00PM') --&gt; Mesmo no formato 24 horas, voc\u00ea consegue especificar o AM\/PM.<\/pre>\n<p>O SQL Server n\u00e3o \u00e9 idiota, portanto\u00a0n\u00e3o tente um 13 da manh\u00e3&#8230;<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"13 da Manh\u00e3 = ERRO!\">SELECT\r\n\tCONVERT(datetime,'01\/01\/2015 13:00AM')<\/pre>\n<p>Curiosamente, isso \u00e9 inv\u00e1lido e gera erro (omitir toda a parte do hor\u00e1rio, exceto as horas):<\/p>\n<pre class=\"lang:tsql decode:true \" title=\"Data completa com somente as horas\">SELECT CONVERT(datetime,'01\/01\/2015 13')\r\nGO<\/pre>\n<p>Por\u00e9m, se voc\u00ea especifica AM ou PM&#8230;<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"Data completa com somente horas e PM\">SELECT CONVERT(datetime,'01\/01\/2015 13PM') \r\nGO\r\n<\/pre>\n<p>Usar separadores de datas for\u00e7a o SQL Server a levar em considera\u00e7\u00e3o a regi\u00e3o. Isto \u00e9, quando voc\u00ea usa um separador na parte dos dias, o SQL Server ir\u00e1 levar em considera\u00e7\u00e3o, por exemplo, o formato\u00a0Brasil (dd\/MM\/AAAA) ou EUA (MM\/dd\/AAAA). A\u00a0data abaixo pode ser 02 de fevereiro ou 01 de janeiro, dependendo de como o SQL Server est\u00e1 interpretando:<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"01 de Fev ou 02 de Jan?\">SELECT CONVERT(datetime,'01\/02\/2015')<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-611\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/setdateformat_trollface.jpg\" alt=\"SET DATEFORMAT n\u00e3o \u00e9 pra exibi\u00e7\u00e3o!\" width=\"360\" height=\"328\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/setdateformat_trollface.jpg 360w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/03\/setdateformat_trollface-300x273.jpg 300w\" sizes=\"auto, (max-width: 360px) 100vw, 360px\" \/>E \u00e9 aqui onde entra o comando <a title=\"BOL - SET DATEFORMAT\" href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms189491.aspx?\">SET DATEFORMAT<\/a>. Este comando \u00e9 muito pol\u00eamico. A maioria dos desenvolvedores acha que ele ir\u00e1 alterar a forma como a data \u00e9 exibida. Pegadinha! Este comando apenas diz para o SQL Server como ele deve considerar o formato das datas de ENTRADA. Ele \u00e9 a maneira de voc\u00ea dizer &#8220;<em>SQL Server, estou te enviando as datas neste formato<\/em>&#8220;. \u00a0 Para saber qual o valor atual do dateformat, voc\u00ea pode executar este SELECT:<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"Consultar o dateformat\">SELECT S.date_format FROM sys.dm_exec_sessions S WHERE S.session_id = @@SPID<\/pre>\n<p>O DATEFORMAT diz\u00a0ao SQL Server onde est\u00e1 o dia, o m\u00eas, e o ano em sua data.\u00a0Cada sess\u00e3o possui seu dateformat, e n\u00e3o afeta o dateformat de outras sess\u00f5es.<\/p>\n<p>O DATEFORMAT\u00a0padr\u00e3o \u00e9 definido quando voc\u00ea se conecta e \u00e9 baseado nas configura\u00e7\u00f5es de idioma do login que voc\u00ea usa pra se conectar. N\u00f3s podemos alterar o DATEFORMAT\u00a0a qualquer momento:<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"dateformat dmy\">SET DATEFORMAT dmy; --&gt; Dia\/M\u00eas\/Ano\r\n\r\nSELECT S.date_format FROM sys.dm_exec_sessions S WHERE S.session_id = @@SPID\r\n\r\nSELECT\r\n\tCONVERT(datetime,'01\/02\/2015') --&gt; O SQL entende isso como 01 de fevereiro!\r\n\t,CONVERT(datetime,'02\/01\/2015') --&gt; O SQL entende isso como 02 de janeiro!\r\n\t,CONVERT(datetime,'13\/01\/2015') --&gt; O SQL entende isso como 13 de janeiro!\r\nGO<\/pre>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #3da871;\">Lembre-se que o SET DATEFORMAT s\u00f3 ir\u00e1 afetar aquela sess\u00e3o em que est\u00e1 se executando o comando. Quando voc\u00ea se desconectar (ou sua aplica\u00e7\u00e3o) do SQL Server, ou mesmo abrir outra sess\u00e3o, o dateformat ser\u00e1 baseado nas configura\u00e7\u00f5es do Login usado para a conex\u00e3o.<\/span><\/strong><\/p>\n<p>Este aqui ir\u00e1 gerar erro, pois, conforme o dateformat configurado, n\u00e3o existe um 01 do 13&#8230;<\/p>\n<pre class=\"lang:tsql decode:true \" title=\"DATEFORMAT dmy error\">SET dateformat dmy;\r\nSELECT CONVERT(datetime,'01\/13\/2015')<\/pre>\n<p>Se voc\u00ea alterar o dateformat, dever\u00e1 alterar o formato de suas datas:<\/p>\n<pre class=\"lang:tsql decode:true \" title=\"DATEFORMAT mdy\">SET DATEFORMAT mdy; \u00a0--&gt;M\u00eas\/Dia\/Ano\r\n\r\nSELECT S.date_format FROM sys.dm_exec_sessions S WHERE S.session_id = @@SPID\r\n\r\nSELECT\r\n\tCONVERT(datetime,'01\/02\/2015') --&gt; O SQL entende isso como 02 de janeiro!\r\n\t,CONVERT(datetime,'02\/01\/2015') --&gt; O SQL entende isso como 01 de fevereiro!\r\nGO\r\n--&gt; Agora este d\u00e1 erro, pois n\u00e3o existe 01 do 13 (o m\u00eas agora vem antes). Quando o DATEFORMAT era dmy funcionava...\r\nSELECT\r\n\tCONVERT(datetime,'13\/01\/2015') \r\nGO\r\n\r\n--&gt; E este que gerava erro em dmy agora d\u00e1 certo!\r\nSELECT\r\n\tCONVERT(datetime,'01\/13\/2015') --&gt;\u00a0Agora d\u00e1 certo, pois o m\u00eas \u00e9 01, e o dia 13. Isso \u00e9 13 de janeiro!\r\nGO<\/pre>\n<p>No caso do ano, se voc\u00ea especificar o ano com 4 d\u00edgitos, o SQL Server detecta onde o ano est\u00e1. Neste caso o dateformat vai valer somente para a posi\u00e7\u00e3o do dia e do m\u00eas:<\/p>\n<pre class=\"lang:tsql decode:true \" title=\"DATEFORMAT e D\u00edgitos do Ano\">SET DATEFORMAT ydm; --&gt; Ano\/Dia\/Mes\r\n\r\n--&gt; Funciona. O SQL Server sabe onde o ano est\u00e1 pelo n\u00famero de d\u00edgitos\r\n--&gt; Por\u00e9m, o dia e o m\u00eas continua valendo. Neste caso o dateformat diz \"dia\" antes de m\u00eas.\r\nSELECT \r\n\tCONVERT(datetime,'01\/03\/2010') \r\n\t,CONVERT(datetime,'03\/01\/2010') \r\nGO\r\n\r\n--&gt; Se voc\u00ea usar 2 d\u00edgitos, ai a brincadeira muda...\r\nSELECT \r\n\tCONVERT(datetime,'01\/03\/20') --&gt; isto significa: ano 01, dia 03, m\u00eas 20. N\u00e3o existe m\u00eas 20, ent\u00e3o d\u00e1 erro!\r\nGO\r\n\r\nSELECT \r\n\tCONVERT(datetime,'20\/03\/01') --&gt; isto significa: ano 2020, dia 03, m\u00eas 01. \r\nGO<\/pre>\n<p>Sim, isso \u00e9 um saco! Felizmente\u00a0voc\u00ea pode contornar isso <strong>apenas deixando de usar os separadores<\/strong>. Sim, meu caro, quando n\u00e3o se usa separadores o SQL Server interpreta a sua data usando o formato ISO 8601 que \u00e9 um formato padr\u00e3o, independente do buraco do mundo onde voc\u00ea esteja! \u00a0Este formato sempre ir\u00e1 considerar AnoM\u00easDia ou AAAA\/MM\/DD\u00a0ou AA\/MM\/DD. <strong>Sempre! Sempre! Independente do DATEFORMAT<\/strong>!<\/p>\n<pre class=\"lang:tsql decode:true\" title=\"Sem Separadores = ISO 8601 = Sem Dor de Cabe\u00e7a \">SET DATEFORMAT dmy;\r\nSELECT CONVERT(datetime,'20130113') --&gt; 13 de janeiro de 2013\r\n\r\nSET DATEFORMAT mdy;\r\nSELECT CONVERT(datetime,'20130113') --&gt; 13 de janeiro de 2013. Aqui o dateformat n\u00e3o tem vez!\r\nSELECT CONVERT(datetime,'920308') --&gt; 08\/03\/1992! Perfeitamente v\u00e1lido! O SQL tamb\u00e9m entende ano com 2 d\u00edgitos!<\/pre>\n<p>E voc\u00ea pode continuar especificando as horas normalmente, j\u00e1 que \u00e9 sempre o mesmo formato, independente da regi\u00e3o:<\/p>\n<pre class=\"lang:tsql decode:true \" title=\"ISO 8601 + Horas = Funciona normalmente!\">SELECT \r\n\tCONVERT(datetime,'20150101 13:45:09')\r\n\t,CONVERT(datetime,'20150101 01:02AM')\r\n\t,CONVERT(datetime,'20150101 00:02:03.123')<\/pre>\n<p>Eu gosto muito deste formato e sempre estou usando nos meus scripts. Mas voc\u00ea deve tomar muito cuidado pra n\u00e3o cometer alguns errinhos:<\/p>\n<pre class=\"lang:tsql decode:true \" title=\"ISO 8601 Errinhos Comuns\">SELECT\r\n\tCONVERT(datetime,'201008') --&gt; Isto n\u00e3o \u00e9 20 de outubro de 2008. Isto \u00e9 \u00a008 de outubro de 2020!\r\n\t,CONVERT(datetime,'191203') --&gt; \u00a0Isso \u00e9 03 de Dezembro de 2019 e n\u00e3o \u00a001 de mar\u00e7o de 1912, ok? \r\n\t\t\t\t\t\t\t\t-- Voc\u00ea pode alterar somente os d\u00edgitos do ano (2 d\u00edgitos ou 4 d\u00edgitos). As outras partes tem de ser com 2 d\u00edgitos!\r\nGO\r\n\r\nSELECT\r\n\tCONVERT(datetime,'15122010') --&gt; Isso seria 10\/20\/1512. Ano correto, dia correto, por\u00e9m n\u00e3o existe m\u00eas 20 jovem...<\/pre>\n<p>Fique atento ao tipos de dados tamb\u00e9m&#8230;<\/p>\n<pre class=\"lang:tsql decode:true \" title=\"Range e Tipos\">SELECT\r\n\tCONVERT(datetime2,'15120110') --&gt; Com os tipos date e datetime2, o ano 1512 \u00e9 facilmente aceit\u00e1vel...\r\nGO\r\n\r\n--&gt; Isso d\u00e1 erro! O tipo datetime j\u00e1 n\u00e3o suporta 1512 e o comando abaixo d\u00e1 pau!\r\n-- Tome cuidado! Fique atento ao range de datas suportados pelo tipo escolhido!\r\n-- Essa dica vale tanto para quando usar separadores, tanto quando n\u00e3o usar!\r\nSELECT\r\n\tCONVERT(datetime,'15120110')<\/pre>\n<p>&nbsp;<\/p>\n<p>Bom, para deixar voc\u00ea respirar um pouco, vou encerrar por aqui. Na pr\u00f3xima semana posto a continua\u00e7\u00e3o! Fique ligado no blog!<\/p>\n<p>&nbsp;<\/p>\n[]&#8217;s<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"seriesmeta\">This entry is part 1 of 3 in the series <a href=\"https:\/\/thesqltimes.com\/blog\/series\/sql-datas-basico\/\" class=\"series-124\" title=\"SQL Server: Esclarecendo Datas e Horas\">SQL Server: Esclarecendo Datas e Horas<\/a><\/div><p>Tempo \u00e9 uma coisa interessante. Dias, anos, horas, minutos, milissegundos&#8230; Em algum momento de sua vida com banco de dados voc\u00ea precisou, ou vai precisar, trabalhar com tempo. Datas e horas nos permitem realizar m\u00e9tricas, organizar compromissos, etc., e a maioria dos sistemas hoje em dia\u00a0necessitam manipular data e hora. O SQL Server fornece um&hellip;&nbsp;<a href=\"https:\/\/thesqltimes.com\/blog\/2015\/03\/14\/sql-datas-parte1\/\" rel=\"bookmark\"><span class=\"screen-reader-text\">1. SQL Server, Datas e Horas<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":601,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"categories":[3,11,7],"tags":[125,131,126,129,130,47,128,73,127],"series":[124],"class_list":["post-562","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-banco-de-dados-2","category-desenvolvimento","category-sql-server","tag-date","tag-dateformat","tag-datetime","tag-datetime2","tag-datetimeoffset","tag-microsoft","tag-precisao","tag-sql-server","tag-time","series-sql-datas-basico"],"_links":{"self":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/562","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/comments?post=562"}],"version-history":[{"count":30,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/562\/revisions"}],"predecessor-version":[{"id":961,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/562\/revisions\/961"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/media\/601"}],"wp:attachment":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/media?parent=562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/categories?post=562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/tags?post=562"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/series?post=562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}