SqlDateTime.MinValue! = DateTime.MinValue, por quê?

Gostaria de saber por que SqlDateTime.MinValue não é o mesmo que DateTime.MinValue?

Acho que a diferença entre os tipos de dados Date do SQL e .NET deriva do fato de que o tipo de dados datetime do SQL Server, seus valores mínimos e máximos e sua precisão são muito mais antigos do que o tipo de dados DateTime do .NET.

Com o advento do .NET, a equipe decidiu que o tipo de dado Datetime deveria ter um valor mínimo mais natural , e 01/01/0001 parece uma escolha bastante lógica, e certamente de uma linguagem de programação , em vez de perspectiva do banco de dados , esse valor é mais natural.

Incidentalmente, com o SQL Server 2008, há vários novos tipos de dados baseados em Data ( Date , Time , DateTime2 , DateTimeOffset ) que realmente oferecem um intervalo e precisão maiores, e mapeiam de perto o tipo de dados DateTime no .NET. Por exemplo, o tipo de dados DateTime2 tem um intervalo de datas de 0001-01-01 a 9999-12-31.

O tipo de dados padrão “datetime” do SQL Server sempre teve um valor mínimo de 01/01/1753 (e de fato ainda tem!). Devo admitir, eu também estava curioso sobre o significado deste valor, assim como algumas escavações .. O que eu encontrei foi o seguinte:

Durante o período entre 1 dC e hoje, o mundo ocidental utilizou dois calendars principais: o calendar juliano de Júlio César e o calendar gregoriano do papa Gregório XIII. Os dois calendars diferem em relação a apenas uma regra: a regra para decidir o que é um ano bissexto. No calendar juliano, todos os anos divisíveis por quatro são anos bissextos. No calendar gregoriano, todos os anos divisíveis por quatro são anos bissextos, exceto que os anos divisíveis por 100 (mas não divisíveis por 400) não são anos bissextos. Assim, os anos de 1700, 1800 e 1900 são anos bissextos no calendar juliano, mas não no calendar gregoriano, enquanto os anos de 1600 e 2000 são anos bissextos em ambos os calendars.

Quando o papa Gregório XIII introduziu seu calendar em 1582, ele também ordenou que os dias entre 4 de outubro de 1582 e 15 de outubro de 1582 fossem omitidos – isto é, ele disse que o dia depois de 4 de outubro deveria ser 15 de outubro. demorou a mudar, no entanto. A Inglaterra e suas colônias não mudaram do calendar juliano para o gregoriano até 1752, portanto, para eles, as datas ignoradas eram entre 4 de setembro e 14 de setembro de 1752. Outros países mudaram em outras ocasiões, mas 1582 e 1752 são as datas relevantes para o ano. SGBDs que estamos discutindo.

Assim, dois problemas surgem com a aritmética de data quando se volta muitos anos. A primeira é, deve saltar anos antes de a mudança ser calculada de acordo com as regras julianas ou gregorianas? O segundo problema é, quando e como os dias ignorados devem ser tratados?

É assim que os Big Oito DBMSs lidam com essas questões:

  • Finja que não houve troca. Isso é o que o SQL Standard parece exigir, embora o documento padrão não seja claro: ele apenas diz que as datas são “limitadas pelas regras naturais para datas usando o calendar gregoriano” – quaisquer que sejam as “regras naturais”. Essa é a opção escolhida pelo DB2. Quando há a pretensão de que as regras de um único calendar sempre se aplicam até mesmo a vezes em que ninguém ouviu falar do calendar, o termo técnico é que um calendar “proléptico” está em vigor. Assim, por exemplo, poderíamos dizer que o DB2 segue um calendar gregoriano proléptico.

  • Evite o problema completamente. A Microsoft e a Sybase definiram seus valores de data mínimos em 1 de janeiro de 1753, com segurança, além do horário em que a América alterou os calendars. Isso é defensável, mas de vez em quando as reclamações surgem de que esses dois DBMSs não têm uma funcionalidade útil que os outros DBMSs possuem e que o SQL Standard exige.

  • Escolha 1582. Isso é o que a Oracle fez. Um usuário da Oracle descobriria que a expressão aritmética de data de 15 de outubro de 1582 menos 4 de outubro de 1582 produz um valor de 1 dia (porque não existe 5 a 14 de outubro) e que a data de 29 de fevereiro de 1300 é válida (porque o salto juliano regra do ano aplica-se). Por que a Oracle enfrentou problemas extras quando o padrão SQL não parece exigir isso? A resposta é que os usuários podem exigir isso. Historiadores e astrônomos usam esse sistema híbrido em vez de um calendar gregoriano proléptico. (Essa também é a opção padrão escolhida pela Sun ao implementar a class GregorianCalendar para Java – apesar do nome, GregorianCalendar é um calendar híbrido.)

Esta citação acima é retirada do seguinte link:

Ajuste de desempenho do SQL: datas no SQL

Como, no SQL Server, a data mínima que pode ser armazenada em um campo de data e hora (1753/1/1) não é igual ao MinValue do tipo de dados DateTime .NET (0001/1/1).

1753 foi a data do primeiro adotante do calendar gregoriano (Inglaterra). Por que isso foi escolhido em 01/01/0001 – é sem dúvida legado de quando o SQL Server era a Sybase nos anos 90. Eles devem ter feito a decisão de projeto no início e a equipe do Microsoft SQL não viu um motivo para alterá-la.

Desde a explosão do .NET e a integração do mesmo no Sql Server, agora existe o object DateTime2 para compatibilidade. Se você é um usuário do NHibernate, você pode fornecer esse tipo em seus mapeamentos de tipos para evitar problemas de DateTime.Min

Datas .NET servem para outros calendars além do Gregoriano:

  • Calendário
    • ChinêsLunisolarCalendário
    • EastAsianLunisolarCalendar
    • Calendário gregoriano
    • HebrewCalendar
    • HijriCalendar
    • JapaneseCalendar
    • JaponêsLunisolarCalendar
    • JulianCalendar
    • KoreanCalendar
    • KoreanLunisolarCalendar
    • PersianCalendar
    • TaiwanCalendário
    • TaiwanLunisolarCalendar
    • TailandêsBudistaCalendário
    • UmAlQuraCalendar

O JulianCalendar infact pré-datas DateTime.MinValue

Dois grupos diferentes decidiram o que “mínimo” significa para eles em relação a data / hora.

SQL usa uma representação interna diferente para DateTime.