Por que as classes Java 8 java.time estão ausentes do método getMillis ()?

64

O Java 8 tem uma biblioteca totalmente nova para datas e horas no pacote java.time, o que é muito bem-vindo para quem já teve que usar o JodaTime antes ou se incomodou em criar seus próprios métodos auxiliares de processamento de datas. Muitas classes neste pacote representam registros de data e hora e têm métodos auxiliares como getHour()obter horas do registro de data e hora, getMinute()minutos do registro de data e hora, getNano()obter nanos do registro de data e hora, etc ...

Notei que eles não têm um método chamado getMillis()para obter o milésimo de tempo. Em vez disso, seria preciso chamar o método get(ChronoField.MILLI_OF_SECOND). Para mim, parece uma inconsistência na biblioteca. Alguém sabe por que esse método está faltando ou como o Java 8 ainda está em desenvolvimento, existe a possibilidade de ser adicionado posteriormente?

https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

As classes definidas aqui representam os principais conceitos de data e hora, incluindo instantes, durações, datas, horas, fusos horários e períodos. Eles são baseados no sistema de calendário ISO, que é o calendário mundial de fato, seguindo as regras gregorianas pró-sépticas. Todas as classes são imutáveis ​​e seguras para threads.

Cada instância de data e hora é composta por campos que são convenientemente disponibilizados pelas APIs. Para acesso de nível inferior aos campos, consulte o java.time.temporalpacote. Cada aula inclui suporte para impressão e análise de todos os tipos de datas e horas. Consulte o java.time.formatpacote para opções de personalização ...

Exemplo deste tipo de classe:
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

Uma data e hora sem fuso horário no sistema de calendário ISO-8601, como 2007-12-03T10: 15: 30.

LocalDateTimeé um objeto de data e hora imutável que representa uma data e hora, geralmente vista como ano-mês-dia-hora-hora-minuto-segundo. Outros campos de data e hora, como dia do ano, dia da semana e semana do ano, também podem ser acessados. O tempo é representado com precisão de nanossegundos. Por exemplo, o valor "2 de outubro de 2007 às 13: 45.30.123456789" pode ser armazenado em um LocalDateTime...

Tarmo
fonte
Parece que eles querem usar o polimorfismo para resolver vários métodos chamados get(), em vez de atribuir nomes únicos e individuais. Se isso lhe incomoda, escreva uma classe que herda a classe original e coloque seu próprio getMillis()método na nova classe.
Robert Harvey
@RobertHarvey A maioria das classes no pacote java.time é imutável e não pode ser estendida.
Assilias
2
@RobertHarvey A questão para mim não é como posso resolver isso. Apenas parecia uma inconsistência estranha e me perguntei se havia uma explicação interessante para isso.
Tarmo
Tenho a ideia de que algumas arquiteturas / sistemas operacionais não oferecem suporte confiável a milissegundos. Em outras palavras, o tempo do sistema não pode ser recuperado em milissegundos, apenas em centésimos ou segundos.
Marco
Veja stackoverflow.com/a/23945792/40064 sobre uma maneira de fazê-lo através da Instantclasse
Wim Deblauwe

Respostas:

63

O JSR-310 é baseado em nanossegundos, não em milissegundos. Como tal, o conjunto mínimo de métodos sensíveis é baseado em hora, minutos, segundo e nanossegundo. A decisão de ter uma base de nanossegundos foi uma das decisões originais do projeto, e que eu acredito fortemente estar correta.

Adicionar um método para milis se sobrepõe ao de nanossegundos é uma maneira não óbvia. Os usuários precisariam pensar se o campo nano era nano-de-segundo ou nano-de-milli, por exemplo. Adicionar um método adicional confuso não é desejável; portanto, o método foi omitido. Como apontado, a alternativa get(MILLI_OF_SECOND)está disponível.

FWIW, eu me oporia a adicionar o getMillis()método no futuro.

JodaStephen
fonte
11
Eu obtive algumas respostas muito boas para essa pergunta, mas sua resposta é a minha favorita, pois é curta e ainda assim faz um argumento muito bom e realmente me convence da necessidade dessa abordagem. Obrigado.
Tarmo
12
@ s3ib se você verificar o perfil do respondente , também notará que ele é um líder de especificação para a própria API que você está perguntando. Isso faz com que uma resposta tão autoritário quanto ele ganha não é mesmo :)
mosquito
Portanto, ter que fazer instant.getEpochSecond * 1000 + instant.getNano / 1000000é uma clichê razoável para poder se comunicar com APIs Java legadas (neste momento, todas), Javascript, etc.?
Nilskp
10
não, nesse caso, você pode simplesmente usar o arquivo instant.toEpochMilli () download.java.net/jdk8/docs/api/java/time/…
JodaStephen
20

Antes de fazer parte do openJDK, o threeten estava no github e antes no sourceforge. Naquela época, Stephen Colebourne, líder de especificação no jsr-310, fez uma pesquisa que você ainda pode encontrar no site do sourceforge .

The fourth question on the survey covered the method names for LocalTime:
1) getHourOfDay(), getMinuteOfHour(), getSecondOfMinute(), getNanoOfSecond()
2) getHour(), getMinute(), getSecond(), getNanoOfSecond()
3) getHour(), getMinute(), getSecond(), getNano()
4) another idea

apenas 6,23% escolheram a resposta 4 e, dentre eles, aproximadamente 15% pediram a getMillis(), ou seja, menos de 1% do total de votos.

Provavelmente, é por isso que não havia, getMillisem primeiro lugar, e não encontrei nada relacionado na lista de discussão do openjdk, de modo que o assunto aparentemente não foi discutido posteriormente.

assylias
fonte
3
Eu acho que dar às pessoas várias opções aumenta a probabilidade de elas escolherem uma dessas opções, mesmo que sua escolha ideal esteja em "outra". Eu posso estar errado, no entanto.
Allon Guralnek
2
@AllonGuralnek Sim, definitivamente - no entanto, o componente de milissegundos era importante na API do Date, porque tudo se baseava em vários milis desde a época. Na nova API, é IMO menos relevante. Na maioria dos casos de uso, você precisa de uma segunda precisão ou a melhor precisão disponível (nanos). Eu posso estar errado.
assylias
11
Isso parece perguntar sobre a nomeação de métodos, e não quais métodos deveriam existir.
svick
11
Certo, desculpe, eu não estava claro: eu quis dizer a pergunta da pesquisa, que ela não busca diretamente relacionada a essa pergunta.
svick
15

As classes que representam horários UTC inequívocos (Instant, OffsetDateTime, ZonedDateTime) têm dois métodos auxiliares para acessar o deslocamento absoluto da época Java, ou seja, o que você chama de 'milissegundo de tempo' no java.util.Date, que você pode usar para chegar em milissegundos

long getEpochSecond()
int getNano()

1000L*getEpochSecond() + getNano() / 1000000L;

Algumas razões pelas quais isso foi escolhido em vez de long getEpochMillis()foram discutidas na lista de discussão do jsr 310 , algumas das quais extraí por conveniência:

parece razoável supor que a precisão de milissegundos não será suficiente. No entanto, qualquer coisa maior que a precisão de nanossegundos parece excessiva

...

Para implementar isso, minha opção preferida seria segundos longos de 64 bits (assinado) + nanossegundos de 32 bits (sem sinal).

...

Prefiro que a divisão esteja no segundo nível, pois essa é a unidade oficial de tempo do SI na ciência e o padrão mais universalmente aceito.

A divisão no nível dos dias é problemática para os instantes, pois não lida com segundos bissextos. A divisão no nível de milissegundos, embora se integre um pouco melhor ao restante do Java, parece realmente bastante estranha. Além disso, perde na faixa suportada.

A divisão no segundo, conforme proposto, fornece uma variedade de instantes de nanossegundos durante 290 bilhões de anos. Embora ninguém jamais deva usar essa precisão nesse intervalo de tempo, sugiro que seja mais fácil apoiá-la do que bloqueá-la. Dividir no nível do dia é problemático para os instantes, pois não lida com segundos bissextos

Sinto que outro motivo foi intencionalmente dificultar a conversão das classes java.util.Date para JSR310, esperando que os desenvolvedores tentassem entender as diferenças entre as várias opções e não apenas usar cegamente as novas classes.

Por que a LocalDateTimeclasse não possui esses métodos - eles não podem existir lá porque LocalDateTimenão está vinculada à linha do tempo UTC até você decidir em que zona está ou qual é o seu deslocamento UTC; nesse momento, você tem um OffsetDateTimeou ZonedDateTime(ambos com os métodos necessários).

Como alternativa, você pode definir sua própria LOCAL_EPOCHconstante 1970-01-01T00:00:00e, em seguida, fazer um MILLIS.between(LOCAL_EPOCH, localTime)para obter algum tipo de duração em milissegundos. Esse valor, no entanto, não será compatível com qualquer valor retornado por System.currentTimeMilliseconds()ou java.util.Date.getTime(), a menos que você defina sua hora local como UTC; mas, nesse caso, você também pode usar o Instant diretamente ou OffsetDateTime com ZoneOffset.UTC.

mkadunc
fonte
4
" eles não podem existir lá porque LocalDateTime não está vinculado à linha do tempo UTC " => um LocalDateTime certamente poderia ter um getMillismétodo que basicamente retornaria getNanos()/1e6- o fato de não ser um instante no tempo não impede que ele tenha um milissegundo componente.
assylias
2
" Sinto que outro motivo foi intencionalmente dificultar a conversão das classes java.util.Date para JSR310 " Provavelmente verdade, mas infelizmente "millis since epoch" se tornou uma representação quase universal do tempo, portanto, para qualquer coisa que precise para se comunicar com APIs Java mais antigas, Javascript, qualquer outra coisa, essa omissão é um verdadeiro aborrecimento.
Nilskp 24/03
Seu trecho de código na parte superior está incorreta - você precisa multiplicar o getEpochSecond por 1000.
Tin Man
@ nilskp São duas coisas diferentes. A pergunta é feita sobre getMillis()como em getMillis-of-second; você está falando de "millis desde a época". O primeiro está ausente, conforme explicado na resposta aceita. O último já está disponível como Instant.toEpochMillis(). Assim, para um LocalDateTime, você iria:ldt.toInstant(offset).toEpochMillis()
SusanW