Working with Dates - Java 8+
Tags: programming, java, tutorial, books
Published: 2022-05-05 12:35:27

# Hints using Dates for Java

Category  |  Description  | Classes
-------  |  -----------  | -------
**Local dates and times** | Represents the local time zone  | _java.time.LocalDate_, _java.time.LocalTime_, _java.time.LocalDateTime_
**Zoned dates and times**  |  These dates and times include time-zone information  |  _java.time.ZonedDateTime_, _java.time.OffsetDateTime_
**Formatters for dates and times** | To parse and print dates and times with patterns and in a variety of styles | _java.time.format.DateTimeFormatter_
**Adjustments to dates and times** | To adjust and manipulate dates and times by handy increments | _java.time.temporal.TemporalAdjusters_, _java.time.temporal.ChronoUnit_ 
**Periods, Durations, and Instants** | To represent an amount of time, periods for days or longer and durations for shorter periods like minutes or seconds, as a specific instant in time | _java.time.Periods_, _java.time.Durations_, *java.time.Instants*

* you need to avoid to use _java.util.Date, java.util.Calendar_,  _java.text.DateFormat_. They are considered old.

## The java.time.* Classes for Dates and Times

* uses the static method *LocalDate.now()* to get the current date;
* uses the static method *LocalTime.now()* to get the current time;
* uses the static method *LocalDate.of()* to generate a *DateTime*;


```java
import java.time.LocalDate;  
import java.time.LocalDateTime;  
import java.time.LocalTime;  
  
public class InstanciandoDatas {  
  
    public static void main(String[] args) {  
        LocalDate data = LocalDate.now();
        LocalTime horario = LocalTime.now();

        LocalDateTime dataHora = LocalDateTime.of(data, horario);
        System.out.println("Data e hora usando LocalDateTime.of(data, horario): " + dataHora);
        
        dataHora = LocalDateTime.now();
        System.out.println("Data e hora usando LocalDateTime.now(): " + dataHora);  
    }  
}
```
```
Data e hora usando LocalDateTime.of(data, horario): 2022-05-04T18:32:49.130299600
Data e hora usando LocalDateTime.now(): 2022-05-04T18:32:49.132294300
```

* to generate custom dates and times:
	* *LocalDate.of(YYYY, MM, DD)*
	* *LocalDate.parse("YYYY-MM-DD")*
	* *LocalTime.of(hh, mm, ss)*
	* *LocalDate.parse("hh:mm:ss")*
	* *LocalDateTime.of(YYYY, MM, DD, hh, mm, ss)*
	* *LocalDate.parse("YYYY-MM-DDThh:mm:ss")*

```java
import java.time.LocalDate;
import java.time.LocalTime;

public class DatasCustomizadas {

    public static void main(String[] args) {
        LocalDate dataInicio = LocalDate.of(2022, 01, 01);
        LocalDate dataFim = LocalDate.parse("2022-01-30");
        System.out.println("Ferias de " + dataInicio + " ate " + dataFim);

        LocalTime horaInicio = LocalTime.of(8,15,30);
        LocalTime horaFim = LocalTime.parse("09:47:55");
        System.out.println("Intervalo de " + horaInicio + " ate " + horaFim);

        LocalDateTime dataHoraInicio = LocalDateTime.of(2022, 12,15, 1, 22, 43);
        LocalDateTime dataHoraFim = LocalDateTime.parse("2022-12-20T05:45:43");
        System.out.println("Recesso de " + dataHoraInicio + " ate " + dataHoraFim);    }   
}
```
```
Ferias de 2022-01-01 ate 2022-01-30
Intervalo de 08:15:30 ate 09:47:55
Recesso de 2022-12-15T01:22:43 ate 2022-12-20T05:45:43
```
* we can use the *DateTimeFormatter* to be used as date time formatter to read a string or to generate a string from a date time.

```java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class FormatandoDatas {

    public static void main(String[] args) {
        String strDataFormatoBR = "25-06-1980 11:15";
        DateTimeFormatter formatoData = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");
        LocalDateTime dataHoraBR = LocalDateTime.parse(strDataFormatoBR, formatoData);
		System.out.println("Data e hora extraidos do formato BR: " + dataHoraBR);

        DateTimeFormatter outroFormato = DateTimeFormatter.ofPattern("dd MM yy - HH, mm");
        System.out.println("Outros formatos: " + dataHoraBR.format(outroFormato));
    }
}
```

```
Data e hora extraidos do formato BR: 1980-06-25T11:15
Outros formatos: 25 06 80 - 11, 15
```

* *LocalDateTime* has several methods that make it easy to add to and subtract from dates and times. Like *.plusHours()*, *.plusDays()*, *.plusMinutes()*, *plusYears()*, *minusWeeks()*, *minusSeconds()*, etc.
* And useful methods like *.getDayOfWeek()*.

```java
import java.time.LocalDate;

public class ManipulandoDatas {

    public static void main(String[] args) {
        LocalDate dataNascimento = LocalDate.of(1980, 6, 25);
        System.out.println("Dia da Semana: " + dataNascimento.getDayOfWeek());
        System.out.println("Três dias antes: " + dataNascimento.minusDays(3));
        System.out.println("Três dias depois: " + dataNascimento.plusDays(3));
    }
}
```
```
Dia da Semana: WEDNESDAY
Três dias antes: 1980-06-22
Três dias depois: 1980-06-28
```

## Zoned Dates and Times

* all time zones are based on *Greenwich Mean Time (GMT)*;
* The name of the time standard that uses GMT as the basis for all other time zones is *Coordinated Universal Time (UTC)*;

```java
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class DataComFuso {

    public static void main(String[] args) {
        LocalDateTime dateTime = LocalDateTime.now();

        ZonedDateTime zonedDateTimeSP = ZonedDateTime.of(dateTime, ZoneId.of("America/Sao_Paulo"));
        ZonedDateTime zonedDateTimeAC = ZonedDateTime.of(dateTime, ZoneId.of("Brazil/Acre"));
        ZonedDateTime zonedDateTimePT = ZonedDateTime.of(dateTime, ZoneId.of("Europe/Lisbon"));

        System.out.println("Data hora fuso SP: " + zonedDateTimeSP);
        System.out.println("Data hora fuso AC: " + zonedDateTimeAC);
        System.out.println("Data hora fuso PT: " + zonedDateTimePT);
    }
}
```

```
Data hora fuso SP: 2022-05-05T00:34:41.243321900-03:00[America/Sao_Paulo]
Data hora fuso AC: 2022-05-05T00:34:41.243321900-05:00[Brazil/Acre]
Data hora fuso PT: 2022-05-05T00:34:41.243321900+01:00[Europe/Lisbon]
```

* The names of the zones are not listed in the documentation page for ZoneId, but you can use this [reference](https://mkyong.com/java8/java-display-all-zoneid-and-its-utc-offset/)
* You can find out if you’re in daylight savings time by using *ZoneRules*.
	* *.isDaylightSavings()* using an _Instant_

```java
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class HorarioDeVerao {

    public static void main(String[] args) {
        LocalDateTime dateTime = LocalDateTime.parse("2018-05-01T05:00:00");
        ZoneId zoneId = ZoneId.of("America/Sao_Paulo");
        ZonedDateTime zonedDateTimeSP = ZonedDateTime.of(dateTime, zoneId);

        boolean isDaylightSaving = zoneId.getRules().isDaylightSavings(zonedDateTimeSP.toInstant());
        System.out.println("Em " + zonedDateTimeSP + " SP esta em horario de verao: " + isDaylightSaving);

        dateTime = LocalDateTime.parse("2018-12-01T05:00:00");
        zonedDateTimeSP = ZonedDateTime.of(dateTime, zoneId);
        isDaylightSaving = zoneId.getRules().isDaylightSavings(zonedDateTimeSP.toInstant());
        System.out.println("Em " + zonedDateTimeSP + " SP esta em horario de verao: " + isDaylightSaving);
    }
}
```
## Date and Time Adjustments

* datetime objects as **“immutable**.
* it is possible to use adjusters, like *TemporalAdjusters*, in a datetime to create new ones.
	* *firstDayOfNextYear()*
	* *lastDayOfMonth()*
	* *withHour()*
	* *withYear()*
```java
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAdjusters;

public class AjustandoDatas {

    public static void main(String[] args) {
        LocalDateTime dateTime = LocalDateTime.parse("2018-05-01T05:00:00");
        ZonedDateTime zonedDateTimeSP = ZonedDateTime.of(dateTime, ZoneId.of("America/Sao_Paulo"));
        System.out.println("O dia " + zonedDateTimeSP + " foi no dia da semana: " + zonedDateTimeSP.getDayOfWeek());

        ZonedDateTime nextFridayDateTime = zonedDateTimeSP.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
        System.out.println("A data da proxima SEXTA foi: " + nextFridayDateTime);
    }
}
```

```
O dia 2018-05-01T05:00-03:00[America/Sao_Paulo] foi no dia da semana: TUESDAY
A data da proxima SEXTA foi: 2018-05-04T05:00-03:00[America/Sao_Paulo]
```
* when we don't need to modify a date considering the zone rules, we need to use the *OffsetDateTime*

## Periods, Durations, and Instants

*  *Periods* represents a period of days, months, or years;
* *Durations*  represents a short period of minutes or hours
* *Instant* represents an intant in time.
	* the number of seconds (and nanoseconds) since January 1, 1970

```java
import java.time.Period;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class UsandoPeriodosDeTempo {

    public static void main(String[] args) {
        ZonedDateTime startDateTime = ZonedDateTime.of(2022, 4, 8, 13, 35, 56, 0, ZoneId.of("America/Sao_Paulo"));

        Period period = Period.ofMonths(3);
        ZonedDateTime endDateTime = startDateTime.plus(period);

        System.out.println("Inicio da Atividade: " + startDateTime);
        System.out.println("Fim da Atividade (+ 3 meses): " + endDateTime);

        System.out.println("\nFim da Atividade com horario de Portugal: " + endDateTime.withZoneSameInstant(ZoneId.of("Europe/Lisbon")));
    }
}
```

```
Inicio da Atividade: 2022-04-08T13:35:56-03:00[America/Sao_Paulo]
Fim da Atividade (+ 3 meses): 2022-07-08T13:35:56-03:00[America/Sao_Paulo]

Fim da Atividade com horario de Portugal: 2022-07-08T17:35:56+01:00[Europe/Lisbon]
```

```java
import java.time.Duration;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class DuracaoDeIntervalo {

    public static void main(String[] args) {
        LocalTime begins = LocalTime.of(12, 07, 10);
        LocalTime ends = LocalTime.of(14, 22, 37);
        System.out.println("Intervalo: " + begins + " - " + ends);

        long minutes = ChronoUnit.MINUTES.between(begins, ends);
        System.out.println("Total minutos: " + begins + " - " + ends);

        Duration duration = Duration.ofMinutes(minutes);
        System.out.println("Duracao do intervalo: " + duration);
    }
}
```

```
Intervalo: 12:07:10 - 14:22:37
Total minutos: 12:07:10 - 14:22:37
Duracao do intervalo: PT2H15M
```

```java
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class UsandoInstant {

    public static void main(String[] args) {
        ZonedDateTime eventDateTime = ZonedDateTime.of(1998, 1, 13, 16, 45, 56, 0, ZoneId.of("America/Sao_Paulo"));
        Instant eventInstant = eventDateTime.toInstant();
        System.out.println("Data e hora do evento: " + eventDateTime);
        System.out.println("Instante do evento: " + eventInstant);

        System.out.println("\nNumero de segundos de 01-Janeiro-1970 ate o inicio do evento: " + eventInstant.getEpochSecond());
    }
}
```
```
Data e hora do evento: 1998-01-13T16:45:56-02:00[America/Sao_Paulo]
Instante do evento: 1998-01-13T18:45:56Z

Numero de segundos de 01-Janeiro-1970 ate o inicio do evento: 884717156
```

## Using Dates and Times with Locales

* the *DateTimeFormatter* class can use an instance of *Locale* to customize formatted output for a specific locale
* The API says a locale is “a specific geographical, political, or cultural region”.
```java
Locale(String language)
Locale(String language, String country)
```
```java
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;

public class UsandoLocale {

    public static void main(String[] args) {
        Locale locBR = new Locale("pt", "BR");
        Locale locJA = new Locale("ja");
        Locale locUS = new Locale("US");


        ZonedDateTime zonedDateTime = ZonedDateTime.now();

        System.out.println("Formato longo: ");
        System.out.println("Brasil: " +
                zonedDateTime.format(
                        DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                                .withLocale(locBR)));
        System.out.println("Japao: " +
                zonedDateTime.format(
                        DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                                .withLocale(locJA)));
        System.out.println("USA: " +
                zonedDateTime.format(
                        DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                                .withLocale(locUS)));

        System.out.println("\nFormato curto: ");
        System.out.println("Brasil: " +
                zonedDateTime.format(
                        DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
                                .withLocale(locBR)));
        System.out.println("Japao: " +
                zonedDateTime.format(
                        DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
                                .withLocale(locJA)));
        System.out.println("USA: " +
                zonedDateTime.format(
                        DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
                                .withLocale(locUS)));
    }
}
```

```
Formato longo: 
Brasil: 5 de maio de 2022 13:14:16 CEST
Japao: 2022年5月5日 13:14:16 CEST
USA: 2022 May 5 13:14:16 CEST

Formato curto: 
Brasil: 05/05/2022 13:14
Japao: 2022/05/05 13:14
USA: 2022-05-05 13:14
```

## SUMMARY
* main methods
 
java.time Class | method example
----------------|---------------|
*LocalDate* |  *LocalDate.now()*; <br> *LocalDate.of(2022, 8, 22)*; <br> *LocalDate.parse("2022-8-22")*;
*LocalTime* | *LocalTime.now()*; <br> *LocalTime.of(11, 20, 37)*; <br> *LocalTime.of("11:20:37");*
*LocalDateTime* | *LocalDateTime.now();* <br> *LocalDateTime.of(aDate, aTime);* <br> *LocalDateTime.parse("2022-05-09T11:20:37");* <br> *LocalDateTime.parse(aDateTime, aFormatter);* <br> *LocalDateTime.parse("2022-09-22T11:20", aFormatter);*
*ZonedDateTime* | *ZonedDateTime.now();* <br> *ZonedDateTime.of(aDateTime, ZoneId.of(aZoneString));* <br> *ZonedDateTime.parse("2018-05-09T11:20:47-03:00")*
*OffsetDateTime* | *OffsetDateTime.now();* <br> *OffsetDateTime.of(aDateTime, ZoneOffset.of("-03:00"));* <br> *OffsetDateTime.parse("2018-04-08T11:19:36-03:00");*
*format.DateTimeFormatter*| *DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");* <br> *DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(aLocale);*
*Instant*| *Instant.now()* <br> *zonedDateTime.toInstant();* <br> *aDateTime.toInstant(ZoneOffset.of("+5"));*
*Duration*|*Duration.between(aDate1, aDate2);* <br> *Duration.ofMinutes(5);*
*Period*|*Period.between(aDate1, aDate2);* <br> *Period.ofDays(3);*
*util.Locale*|*Locale.getDefault();* <br> *new Locale(String language);* <br> *new Locale(String language, String country);*

java.time Class | adjustment example
----------------|---------------|
*LocalDate* | *aDate.minusDays(3);* <br> *aDate.plusWeeks(1);* <br> *aDate.withYear(2018);*
*LocalTime* | *aTime.minus(3, ChronoUnit.MINUTES);* <br> *aTime.plusMinutes(3);* <br> *aTime.withHour(12);* 
*LocalDateTime* | *aDateTime.minusDays(3);* <br> *aDateTime.plusMinutes(10);* <br> *aDateTime.plus(Duration.ofMinutes(5));* <br> *aDateTime.withMonth(2);*
*ZonedDateTime* | *zonedDateTime.withZoneSameInstant(ZoneId.of("US/Pacific"));*

## REFERENCES
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/format/DateTimeFormatter.html

https://mkyong.com/java8/java-display-all-zoneid-and-its-utc-offset/

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/package-summary.html