Opa boa boa excelentes pontos esses, me fizeram pensar em algumas coisas:
De fato ChronoUnit e ChronoField são descritas de forma bem parecida, eu fui dar uma olhada no JavaDoc delas e saca só:
/**
* A standard set of fields.
* <p>
* This set of fields provide field-based access to manipulate a date, time or date-time.
* The standard set of fields can be extended by implementing {@link TemporalField}.
* <p>
* These fields are intended to be applicable in multiple calendar systems.
* For example, most non-ISO calendar systems define dates as a year, month and day,
* just with slightly different rules.
* The documentation of each field explains how it operates.
*
* @implSpec
* This is a final, immutable and thread-safe enum.
*
* @since 1.8
*/
public enum ChronoField implements TemporalField {
/**
* A standard set of date periods units.
* <p>
* This set of units provide unit-based access to manipulate a date, time or date-time.
* The standard set of units can be extended by implementing {@link TemporalUnit}.
* <p>
* These units are intended to be applicable in multiple calendar systems.
* For example, most non-ISO calendar systems define units of years, months and days,
* just with slightly different rules.
* The documentation of each unit explains how it operates.
*
* @implSpec
* This is a final, immutable and thread-safe enum.
*
* @since 1.8
*/
public enum ChronoUnit implements TemporalUnit {
A ChronoField
é um "conjunto de campos padrão" e ChronoUnit
é descrita como "um conjunto padrão de unidades de período de datas".
De fato por descrição são praticamente a mesma coisa.
Mas vamos imaginar que eu quero somar 10 dias na data atual, eu faria algo mais ou menos assim:
LocalDate value = LocalDate.now().plus(10, ChronoUnit.DAYS);
Como a assinatura do método plus()
espera receber um TemporalAmount
ou um valor inteiro e um TemporalUnit
então só é possível utilizar ChronoUnit
que implementa a interface (é um) TemporalUnit
.
Da mesma forma, vamos dizer que eu queira saber em que mês estamos, eu teria de fazer
LocalDate.now().get(ChronoField.MONTH_OF_YEAR);
Nesse caso o método get()
espera receber um TemporalField
, logo não é possível utilizar ChronoUnit
e por isso utilizamos ChronoField
que implementa a interface (é um) TemporalField
.
Quanto a semântica, penso o seguinte:
ChronoUnit
Uma unidade deve ser utilizada para medir uma quantidade de tempo - anos, meses, dias, horas, minutos, segundos. Por exemplo, o segundo é uma unidade do S.I.
ChronoField
Por outro lado, os campos são como os humanos geralmente se referem ao tempo, que é em partes. Se você olhar para um relógio digital, os segundos contam de 0 a 59 e depois voltam para 0 novamente.
Este é um campo - "segundo do minuto" neste caso, formado pela contagem de segundos dentro de um minuto.
Da mesma forma, os dias são contados dentro de um mês e os meses dentro de um ano. Para definir um ponto completo na linha do tempo, você precisa ter um conjunto de campos vinculados, por exemplo:
- segundo de minuto
- minuto-a-hora
- hora do dia
- dia do mês
- mês do ano
- ano (-de-para-sempre)
A API ChronoField expõe as duas partes do segundo do minuto.Podemos utilizar getBaseUnit()
para obter "segundos" e getRangeUnit()
para obter "minutos".
A parte Chrono do nome refere-se ao fato de que as definições são cronologicamente neutras. Especificamente, isso significa que a unidade ou campo tem significado apenas quando associado a um sistema de calendário ou cronologia. Um exemplo disso é a cronologia copta, onde há 13 meses em um ano. Apesar de ser diferente do sistema de calendário civil/ISO comum, a constante ChronoField.MONTH_OF_YEAR ainda pode ser usada.
As interfaces TemporalUnit e TemporalField fornecem a abstração de nível mais alto, permitindo que unidades/campos que não são cronologicamente neutros sejam adicionados e processados.
Não sei se ficou mais claro ou mais confuso, mas pelo menos acho que eu entendi melhor um pouco sobre essa duas enums e sua utilização.
Penso que talvez pudessem ter feito uma única enum pra tudo, porém acredito que tiverem alguns motivos pra ter as duas, sendo o primeiro deles querer separar unidades de campos para que aquele que lê o código possa entender mais rapidamente do que se trata aquele código.