O que há de errado com a API Java Date & Time? [fechadas]
105
Freqüentemente, encontro comentários negativos sobre Java Datee outras classes relacionadas a datas. Sendo um desenvolvedor .NET, não consigo entender totalmente (sem tê-los usado) o que há de errado com eles.
Ah, a Dateclasse Java . Talvez um dos melhores exemplos de como não fazer algo em qualquer idioma, em qualquer lugar. Por onde começo?
Ler o JavaDoc pode levar alguém a pensar que os desenvolvedores realmente têm algumas boas idéias. Ele continua sobre a diferença entre UTC e GMT , apesar do fato de que a diferença entre os dois é basicamente segundos bissextos (o que acontece muito raramente ).
No entanto, as decisões de design realmente desperdiçam qualquer ideia de ser uma API bem projetada. Aqui estão alguns dos erros favoritos:
Apesar de ter sido projetado na última década do milênio, ele avalia os anos como dois dígitos desde 1900. Existem literalmente milhões de soluções alternativas realizando mais de 1900 (ou 1900-) no mundo Java como resultado dessa decisão banal.
Os meses são indexados a zero, para atender ao caso espetacularmente incomum de ter uma matriz de meses e não viver com uma matriz de treze elementos, o primeiro dos quais contendo um null. Como resultado, temos 0..11 (e hoje sendo o mês 11 do ano 109). Há um número semelhante de ++ e - nos meses para converter em string.
Eles são mutáveis . Como resultado, toda vez que você quiser retornar uma data (digamos, como uma estrutura de instância), você precisará retornar um clone dessa data em vez do próprio objeto de data (caso contrário, as pessoas podem alterar sua estrutura).
O Calendar, projetado para 'consertar' isso, na verdade comete os mesmos erros. Eles ainda são mutáveis.
Daterepresenta a DateTime, mas para diferir para aqueles no terreno do SQL, há outra subclasse java.sql.Date, que representa um único dia (embora sem um fuso horário associado a ele).
Não há TimeZones associados a um Datee, portanto, os intervalos (como um 'dia inteiro') são frequentemente representados como meia-noite a meia-noite (geralmente em algum fuso horário arbitrário)
Por fim, é importante notar que os segundos bissextos geralmente se corrigem em relação a um bom relógio do sistema, que é atualizado com ntp em uma hora (veja os links abaixo). A chance de um sistema ainda estar ativo e em execução na introdução de dois segundos bissextos (a cada seis meses no mínimo, praticamente a cada poucos anos) é bastante improvável, especialmente considerando o fato de que você precisa reimplantar novas versões de seu código de vez em quando . Mesmo o uso de uma linguagem dinâmica que regenera classes ou algo como um mecanismo WAR poluirá o espaço da classe e acabará sem permgen.
JSR 310 , que suplantou as antigas classes de data e hora com java.time no Java 8, se justifica no JSR original da seguinte maneira:
2.5 Que necessidade da comunidade Java será atendida pela especificação proposta?
Atualmente Java SE tem duas APIs de data e hora separadas - java.util.Date e java.util.Calendar. Ambas as APIs são consistentemente descritas como difíceis de usar por desenvolvedores Java em weblogs e fóruns. Notavelmente, ambos usam um índice zero por meses, o que é a causa de muitos bugs. O Calendar também sofreu com muitos bugs e problemas de desempenho ao longo dos anos, principalmente devido ao armazenamento interno de seu estado de duas maneiras diferentes.
Um bug clássico (4639407) impedia que certas datas fossem criadas em um objeto Calendário. Pode ser escrita uma sequência de código que pode criar uma data em alguns anos, mas não em outros, tendo o efeito de impedir que alguns usuários insiram suas datas de nascimento corretas. Isso foi causado pela classe Calendar permitindo apenas um ganho de horário de verão de uma hora no verão, quando historicamente era mais 2 horas em torno da época da segunda guerra mundial. Embora esse bug agora tenha sido corrigido, se em algum ponto no futuro um país optasse por introduzir um ganho de horário de verão de mais três horas no verão, a classe Calendário seria novamente quebrada.
A API Java SE atual também sofre em ambientes multithread. As classes imutáveis são conhecidas por serem inerentemente thread-safe, pois seu estado não pode ser alterado. No entanto, tanto a data quanto o calendário são mutáveis, o que exige que os programadores considerem a clonagem e o encadeamento explicitamente. Além disso, a falta de segurança de thread em DateTimeFormat não é amplamente conhecida e tem sido a causa de muitos problemas de threading difíceis de rastrear.
Assim como os problemas com as classes que o Java SE possui para datetime, ele não possui classes para modelar outros conceitos. Datas ou horas fora do fuso horário, durações, períodos e intervalos não têm representação de classe em Java SE. Como resultado, os desenvolvedores frequentemente usam um int para representar uma duração de tempo, com javadoc especificando a unidade.
A falta de um modelo abrangente de data e hora também faz com que muitas operações comuns sejam mais complicadas do que deveriam. Por exemplo, calcular o número de dias entre duas datas é um problema particularmente difícil no momento.
Este JSR resolverá o problema de um modelo completo de data e hora, incluindo datas e horas (com e sem fusos horários), durações e períodos de tempo, intervalos, formatação e análise.
As instâncias de data são mutáveis , o que quase sempre é inconveniente.
Eles têm uma natureza dupla. Eles representam um carimbo de data / hora e uma data do calendário. Acontece que isso é problemático ao fazer cálculos em datas.
As representações numéricas dos dados do calendário são contra-intuitivas em muitos casos. Por exemplo: getMonth()é baseado em zero, getYear()é baseado em 1900 (ou seja, o ano de 2009 é representado como 109).
Eles estão perdendo muitas funcionalidades que você espera de uma Dateclasse.
Sinto por você ... como ex-programador .NET, fiz as mesmas perguntas, a API de tempo em .NET (timespans, sobrecarga de operador) é muito conveniente.
Primeiro, para criar uma data específica, você usa uma API obsoleta ou:
Calendar c =Calendar.getInstance();
c.set(2000,31,12)
Para subtrair um dia você faz coisas más como
Date firstDate =...Calendar c =Calendar.getInstance();
c.setTime(fistDate);
c.add(Calendar.DATE,-1);Date dayAgo = c.getTime();
ou pior
Date d =newDate();Date d2 =newDate(d.getTime()-1000*60*60*24);
Para saber quanto tempo se passou entre duas datas (em dias / semanas / meses) ... fica ainda pior
No entanto, DateUtils de apache ( org.apache.commons.lang.time.DateUtils) oferece alguns métodos convenientes e eu me descobri usando apenas eles recentemente
Como escreveu Brabster, Joda Time também é uma boa biblioteca externa, mas o apache parece mais "comum" do que qualquer outra coisa ...
@AntonGogolev Em java.time , use as classes Periode Durationpara calcular e representar o tempo decorrido em uma escala de anos-meses-dias e horas-minutos-segundos, respectivamente.
Basil Bourque
4
Acho que a API Date do Java pode ser usada, para ser honesto. A maioria das questões que eu vi e ouvi sobre se relacionam com a verbosidade, a necessidade de envolver várias classes para fazer algo útil ( Calendar, Date, DateFormat/ SimpleDateFormat) ea falta de assessores simples como getDayOfWeek().
Joda Time é uma API alternativa bem respeitada em Java, e na seção Why Joda Time ele fornece mais alguns argumentos sobre porque é uma alternativa viável que pode ser de interesse.
Respostas:
Ah, a
Date
classe Java . Talvez um dos melhores exemplos de como não fazer algo em qualquer idioma, em qualquer lugar. Por onde começo?Ler o JavaDoc pode levar alguém a pensar que os desenvolvedores realmente têm algumas boas idéias. Ele continua sobre a diferença entre UTC e GMT , apesar do fato de que a diferença entre os dois é basicamente segundos bissextos (o que acontece muito raramente ).
No entanto, as decisões de design realmente desperdiçam qualquer ideia de ser uma API bem projetada. Aqui estão alguns dos erros favoritos:
null
. Como resultado, temos 0..11 (e hoje sendo o mês 11 do ano 109). Há um número semelhante de ++ e - nos meses para converter em string.Calendar
, projetado para 'consertar' isso, na verdade comete os mesmos erros. Eles ainda são mutáveis.Date
representa aDateTime
, mas para diferir para aqueles no terreno do SQL, há outra subclassejava.sql.Date
, que representa um único dia (embora sem um fuso horário associado a ele).TimeZone
s associados a umDate
e, portanto, os intervalos (como um 'dia inteiro') são frequentemente representados como meia-noite a meia-noite (geralmente em algum fuso horário arbitrário)Por fim, é importante notar que os segundos bissextos geralmente se corrigem em relação a um bom relógio do sistema, que é atualizado com ntp em uma hora (veja os links abaixo). A chance de um sistema ainda estar ativo e em execução na introdução de dois segundos bissextos (a cada seis meses no mínimo, praticamente a cada poucos anos) é bastante improvável, especialmente considerando o fato de que você precisa reimplantar novas versões de seu código de vez em quando . Mesmo o uso de uma linguagem dinâmica que regenera classes ou algo como um mecanismo WAR poluirá o espaço da classe e acabará sem permgen.
fonte
JSR 310 , que suplantou as antigas classes de data e hora com java.time no Java 8, se justifica no JSR original da seguinte maneira:
fonte
getMonth()
é baseado em zero,getYear()
é baseado em 1900 (ou seja, o ano de 2009 é representado como 109).Date
classe.fonte
Sinto por você ... como ex-programador .NET, fiz as mesmas perguntas, a API de tempo em .NET (timespans, sobrecarga de operador) é muito conveniente.
Primeiro, para criar uma data específica, você usa uma API obsoleta ou:
Para subtrair um dia você faz coisas más como
ou pior
Para saber quanto tempo se passou entre duas datas (em dias / semanas / meses) ... fica ainda pior
No entanto, DateUtils de apache (
org.apache.commons.lang.time.DateUtils
) oferece alguns métodos convenientes e eu me descobri usando apenas eles recentementeComo escreveu Brabster, Joda Time também é uma boa biblioteca externa, mas o apache parece mais "comum" do que qualquer outra coisa ...
fonte
Period
eDuration
para calcular e representar o tempo decorrido em uma escala de anos-meses-dias e horas-minutos-segundos, respectivamente.Acho que a API Date do Java pode ser usada, para ser honesto. A maioria das questões que eu vi e ouvi sobre se relacionam com a verbosidade, a necessidade de envolver várias classes para fazer algo útil (
Calendar
,Date
,DateFormat
/SimpleDateFormat
) ea falta de assessores simples comogetDayOfWeek()
.Joda Time é uma API alternativa bem respeitada em Java, e na seção Why Joda Time ele fornece mais alguns argumentos sobre porque é uma alternativa viável que pode ser de interesse.
fonte