Os desenvolvedores geralmente precisam realizar operações de programação, como recuperar a data atual, manipular datas e formatar datas em seus aplicativos. Embora o Java seja tradicional java.util.Calendar
a aula teve seu dia, o mais novo LocalDate
class faz mais com significativamente menos linhas de código. Este artigo apresenta a você LocalDate
e a java.time
API para usar datas, horas e durações em seus programas.
Observação: Introduzido em Java 8, java.time
padroniza muitos elementos da popular biblioteca Joda-Time. Os conceitos introduzidos aqui podem ser aplicados a qualquer biblioteca, mas o padrão JDK é geralmente recomendado.
Substitua Calendário por LocalDate
A manipulação de datas do calendário é um aspecto essencial de muitos aplicativos escritos em Java. Tradicionalmente, os desenvolvedores dependiam do java.util.Calendar
class para obter a data atual:
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // Note: Months are zero-based
int day = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(year + "-" + month + "-" + day);
O LocalDate
aula do java-time
API oferece uma alternativa mais eficiente::
LocalDate currentDate = LocalDate.now();
System.out.println(currentDate);
Neste exemplo, você vê a diferença entre a verbosidade do tradicional Calendar
classe e o mais recente LocalDate
aula. A classe mais recente faz mais com muito menos código. A seguir, veremos algumas maneiras simples de usar java.time.LocalDate em seus programas Java.
Maneiras simples de usar LocalDate
Veja como usaríamos LocalDate
para retornar a data atual com base no relógio do sistema:
System.out.println(LocalDate.now());
Aqui, criamos um LocalDate
instância com o ano, mês e dia especificados:
System.out.println(LocalDate.of(2023, 9, 19));
Neste próximo exemplo, analisamos uma representação de string de uma data e retornamos um LocalDate
instância:
String dateString = "2024-04-19"; // ISO-8601 format
LocalDate date = LocalDate.parse(dateString);
System.out.println(date);
Nos casos em que tivermos a data formatada de forma diferente da ISO-8601, poderíamos usar o seguinte:
String dateString = "19/04/2024"; // Custom format
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date = LocalDate.parse(dateString, formatter);
System.out.println(date);
Estes são apenas alguns exemplos do LocalDate
classe sendo usada para cenários de aplicação onde a manipulação da data do calendário é necessária. Agora vamos examinar usos mais complexos para LocalDate
.
Manipulando componentes de data específicos
Às vezes, precisamos ser capazes de trabalhar com os componentes de uma data, como dia, mês, ano, hora, minuto ou segundo. Exemplos de operações incluem comparar, calcular ou validar informações de data.
Aqui está um exemplo de como chamar componentes de data específicos:
import java.time.LocalDate;
LocalDate date = LocalDate.now(); // Get the current date
System.out.println("Year: " + date.getYear()); // prints the year of the current date
System.out.println("Month: " + date.getMonthValue()); // prints the month of the current date
System.out.println("Day: " + date.getDayOfMonth()); // // prints the day of the current date
System.out.println("Hour: " + dateTime.getHour()); // Prints the hour of the current date
System.out.println("Minute: " + dateTime.getMinute()); // Prints the minute of the current date
System.out.println("Second: " + dateTime.getSecond()); // Prints the second of the current date
Contando dias, meses ou anos
E os casos em que precisamos somar ou subtrair dias, meses ou anos da data do calendário especificada? Veja como LocalDate
lida com este caso de uso:
plusDays(int days) - Adds or subtracts the specified days from the date and returns a new LocalDate instance.
minusDays(int days) - Subtracts days from the date.
plusMonths(int months) - Adds the specified number of months to the date and returns a new LocalDate instance.
minusMonths(int months): Subtracts months from the date.
plusYears(int years) - Adds the specified years from the date and returns a new LocalDate instance.
minusYears(int years) - Subtracts years from the date.
Resolvendo o desafio do ano bissexto
Um ano bissexto é um ano civil que contém um dia adicional, ou 366 dias versus os 365 normais. Qualquer programa que use datas de calendário também deve levar em conta anos bissextos. Felizmente, java.time
de Year
class lida com esse cálculo para nós:
isLeapYear(): Returns true if the year is a leap year
Duas maneiras de comparar datas
Comparar datas é algo que fazemos com frequência na programação. Esta é uma maneira mais antiga de comparar datas usando LocalDate
e a compareTo
método:
import java.time.LocalDate;
LocalDate date1 = LocalDate.now(); // Create the first date object
LocalDate date2 = LocalDate.now(); // Create the second date object
// Compare dates using the compareTo() method
int comparison = date1.compareTo(date2);
if (comparison < 0) {
System.out.println("Date 1 is before Date 2");
} else if (comparison > 0) {
System.out.println("Date 1 is after Date 2");
} else if (comparison == 0) {
System.out.println("Date 1 is equal to Date 2");
}
Uma maneira mais intuitiva e limpa de comparar datas é usar o isBefore
, isAfter
ou isEqual
métodos:
if (date1.isBefore(date2)) {
System.out.println("Date 1 is before Date 2");
} else if (date1.isAfter(date2)) {
System.out.println("Date 1 is after Date 2");
} else if (date1.isEqual(date2)) {
System.out.println("Date 1 is equal to Date 2");
}
Calculando a duração em unidades temporais
Outro requisito comum para aplicativos de negócios é a capacidade de calcular distâncias temporais em unidades temporais. O java.time
A API nos permite fazer isso facilmente.
Este exemplo calcula a duração entre dois pontos no tempo medido em horas e minutos:
import java.time.LocalDateTime;
import java.time.Duration;
public class DurationExample {
public static void main(String() args) {
LocalDateTime start = LocalDateTime.of(2024, 4, 1, 10, 0); // April 1, 2024, 10:00
LocalDateTime end = LocalDateTime.of(2024, 4, 2, 11, 30); // April 2, 2024, 11:30
Duration duration = Duration.between(start, end);
long hours = duration.toHours();
long minutes = duration.toMinutes() % 60;
System.out.println("Duration is " + hours + " hours and " + minutes + " minutes.");
}
}
Neste caso, o tempo de duração é de 25 horas e 30 minutos.
Aqui, calculamos a duração entre duas datas em anos, meses e dias:
import java.time.LocalDate;
import java.time.Period;
public class PeriodExample {
public static void main(String() args) {
LocalDate startDate = LocalDate.of(2024, 1, 1);
LocalDate endDate = LocalDate.of(2024, 12, 31);
Period period = Period.between(startDate, endDate);
System.out.println("Period is " + period.getYears() + " years, " +
period.getMonths() + " months, and " +
period.getDays() + " days.");
}
}
A saída neste caso é 0 anos, 11 meses e 30 dias.
Lidando com fusos horários
Ao trabalhar em um aplicativo em produção, você pode encontrar bugs devido a fusos horários configurados incorretamente. Às vezes, o aplicativo é implantado em um servidor com fuso horário diferente do país em que é servido. Vejamos maneiras de gerenciar diferenças em fusos horários usando java.time
classes e métodos.
Primeiro, podemos usar o ZonedDateTime
classe para gerenciar uma data e hora com informações de fuso horário. Veja como obter a hora atual para dois fusos horários específicos:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class TimeZoneExample {
public static void main(String() args) {
ZoneId newYorkZone = ZoneId.of("America/New_York");
ZoneId londonZone = ZoneId.of("Europe/London");
ZonedDateTime nowInNewYork = ZonedDateTime.now(newYorkZone);
ZonedDateTime nowInLondon = ZonedDateTime.now(londonZone);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println("Current time in New York: " + nowInNewYork.format(formatter));
System.out.println("Current time in London: " + nowInLondon.format(formatter));
}
}
Se executarmos este código em 19 de abril de 2024, às 12h UTC, a saída seria a seguinte:
- Hora local em Nova York: 19/04/2024 08:00:00
- Hora local em Londres: 19/04/2024 13:00:00
Que tal converter entre fusos horários? Veja como converter um determinado horário de uma zona para outra:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class TimeZoneConversion {
public static void main(String() args) {
LocalDateTime localDateTime = LocalDateTime.of(2024, 4, 19, 15, 30);
ZoneId originalZone = ZoneId.of("Asia/Tokyo");
ZoneId targetZone = ZoneId.of("America/Los_Angeles");
ZonedDateTime originalZonedDateTime = ZonedDateTime.of(localDateTime, originalZone);
ZonedDateTime targetZonedDateTime = originalZonedDateTime.withZoneSameInstant(targetZone);
System.out.println("Time in Tokyo: " + originalZonedDateTime);
System.out.println("Time in Los Angeles: " + targetZonedDateTime);
}
}
A saída neste caso seria:
- Horário em Tóquio: 2024-04-19T15:30+09:00(Ásia/Tóquio)
- Horário em Los Angeles: 2024-04-19T01:30-07:00(América/Los_Angeles)
Transições para horário de verão
As transições do horário de verão (DST) podem interromper a funcionalidade do seu aplicativo se não forem tratadas adequadamente. Veja como lidar com uma transição de horário de verão usando o ZonedDateTime
aula:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class TimeZoneConversion {
public static void main(String() args) {
LocalDateTime localDateTime = LocalDateTime.of(2024, 4, 19, 15, 30);
ZoneId originalZone = ZoneId.of("Asia/Tokyo");
ZoneId targetZone = ZoneId.of("America/Los_Angeles");
ZonedDateTime originalZonedDateTime = ZonedDateTime.of(localDateTime, originalZone);
ZonedDateTime targetZonedDateTime = originalZonedDateTime.withZoneSameInstant(targetZone);
System.out.println("Time in Tokyo: " + originalZonedDateTime);
System.out.println("Time in Los Angeles: " + targetZonedDateTime);
}
}
Aqui está o resultado deste cálculo:
- Antes do final do horário de verão: 2024-11-03T01:30-04:00(América/Nova_Iorque)
- Após o término do horário de verão: 2024-11-03T01:30-05:00(América/Nova_Iorque)
Conclusão
Os desenvolvedores lidam com datas e horários na maioria dos aplicativos. O java.time
API incorpora elementos do obsoleto joda-time
biblioteca e os padroniza do Java 8 em diante. Como você viu neste artigo, java.time
oferece muitas construções poderosas para gerenciar data e hora em seus aplicativos.
Vamos recapitular os principais pontos deste artigo:
- O
java.time
O pacote fornece uma abordagem mais clara e intuitiva para lidar com datas e horas em comparação com o tradicionaljava.util.Calendar
aula. - Usando
java.time
permite realizar operações como recuperar a data atual, manipular datas e formatar com menos linhas de código e menos complexidade. java.time
Funções de API comoplusDays()
eminusMonths()
suporta aritmética de data simples que é mais complicada de fazer com oCalendar
aula.- Métodos mais recentes, como
isBefore()
,isAfter()
eisEqual()
oferecem uma maneira mais legível e direta de comparar datas do que usarcompareTo()
. ZonedDateTime
simplifica o gerenciamento avançado de fuso horário e os cálculos de horário de verão, fornecendo ferramentas robustas para aplicações globais.- O
java.time
A biblioteca oferece suporte a poderosas opções de formatação e análise de data que são mais fáceis de usar e entender do que as classes tradicionais de data e hora Java, melhorando a legibilidade e a manutenção do código. - A moderna biblioteca de data e hora foi projetada para ser imutável e segura para threads, o que resulta em menos efeitos colaterais e erros em ambientes multithread.
Para novos projetos ou ao manter aplicações Java existentes, recomenda-se fazer a transição para o java.time
API por seu tratamento mais eficiente, claro e robusto de operações de data e hora.