Habēmus Java 8
Finalmente Java sabe trabalhar com datas e
horários
Por que uma nova API?
public boolean isMesNatal(Calendar calendar){
return calendar.get(Calendar.MONTH) == 11;
}
public boolean isMesNatal(Calendar calendar){
return calendar.get(Calendar.MONTH) == 11;
}
Por que uma nova API?
Dezembro == 11
Por que uma nova API?
Calendar dataNascimento = Calendar.getInstance();
dataNascimento.set(1983, Calendar.NOVEMBER, 15);
Pessoa pessoa = new Pessoa(dataNascimento);
//Afirmação válida
assert pessoa.getDataNascimento()
.get(Calendar.DAY_OF_MONTH) == 15;
Por que uma nova API?
Calendar dataNascimento = Calendar.getInstance();
dataNascimento.set(1983, Calendar.NOVEMBER, 15);
Pessoa pessoa = new Pessoa(dataNascimento);
pessoa.getDataNascimento().add(Calendar.DAY_OF_MONTH, 10);
//Afirmação inválida
assert pessoa.getDataNascimento()
.get(Calendar.DAY_OF_MONTH) == 15;
Calendar
é mutável
Por que uma nova API?
public class Pessoa{
private Calendar dataNascimento; // encapsulada
public Pessoa(Calendar dataNascimento){
this.dataNascimento = dataNascimento;
}
public Calendar getDataNascimento() {
return (Calendar)
this.dataNascimento.clone();
}
}
Por que uma nova API?
long duracao = turno.getDuracao();
// horas? minutos? milisegundos?
Por que uma nova API?
public class Turno {
/**
* @return duração de um turno de
* trabalho em milisegundos
*/
public long getDuracao(){ … }
}
Evolução
1996 - java.util.Date (JDK 1.0)
1997 - java.util.Calendar (JDK 1.1)
2005 - Joda-Time (third library)
2007 - JSR-310
JSR 310
● Início oficial em 30/01/2007
● Líderes
○ Stephen Colebourne
○ Michael Nascimento Santos
○ Roger Riggs
● Baseada fortemente no Joda Time
○ http://blog.joda.org/2009/11/why-jsr-310-isn-joda-
time_4941.html
Date Time API
JDK 1.8
Princípios fundamentais
● Imutável
● Modelo rico, compreensível e fluente
● Separação de cronologias
Rico modelo de
dados
Explorando alguns dos novos tipos de dados
disponíveis
Datas
● LocalDate
○ Datas consistêm em dia, mês e ano
○ Data de nascimento, feriado, emissão de NF
LocalDate.of(2014, Month.MAY, 17);
Horas
● LocalTime
○ Horários consitêm em hora, minutos e segundos
○ Horário de início do expediente, horário do
despertador
LocalTime.of(13, 10);
Datas e horas
● LocalDateTime
○ Composto por data e horas
○ Data e hora de um atendimento médico, entrada de
log, marcação de ponto
LocalDateTime.of(2014, Month.MAY, 17, 13, 10);
Mais modelos
● YearMonth
○ ano e mês de alistamento militar
● MonthDay
○ mês e dia de nascimento
● Year
○ ano de fabricação de um automóvel
● Instant
○ um ponto na linha do tempo
○ remete à classe j.u.Date
Mais modelos
● DayOfWeek
○ enum com os dias da semana, SUNDAY,
MONDAY..
● Month
○ enum com os meses do ano JANUARY,
FEBRUARY
● ZonedDateTime
○ Time-zones são tratadas separadamente
○ Data e hora em um determinado time-zone
■ Remete à classe java.util.Calendar
A partir do Java 8 será
muito importante a escolha
correta do tipo de dado
baseado na necessidade de
cada aplicação.
Formatação e Parsing
● LocalDate.now().format(...)
● LocalDate.parse(...)
● Resolve o problema de thread-safety da API
atual
Períodose durações
● Period
○ Montante de tempo em termos de dias, meses e
anos
■ 2 anos, 5 meses e 7 dias
● Duration
○ Montante de tempo em termos de tempo
■ 36 segundos
■ 5 horas
■ Porém suporta o conceito de dias com 24 horas
Adjusters
● Usado para alterações complexas
○ ajustar uma data para o último dia do mês
○ ajustar uma data para o proximo dia útil
public interface TemporalAdjuster {
Temporal adjustInto(Temporal entrada);
}
LocalDate dataAjustada = data.with(ultimoDiaDoMes());
LocalDate dataAjustada = data.with(proximoDiaUtil());
Adjusters
// 2000-10-15, domingo
LocalDate date = LocalDate.of(2000, Month.OCTOBER,
15);
// primeiro dia do mês: 2000-10-01
date.with(TemporalAdjusters.firstDayOfMonth());
// Primeira segunda do mês: 2000-10-02
date.with(TemporalAdjusters.firstInMonth(
DayOfWeek.MONDAY));
// último dia do mês: 2000-10-31
date.with(TemporalAdjusters.lastDayOfMonth());
Adjusters
// primeiro dia do próximo mês: 2000-11-01
date.with(TemporalAdjusters.firstDayOfNextMonth());
// primeiro dia do próximo ano: 2001-01-01
date.with(TemporalAdjusters.firstDayOfNextYear());
// primeiro dia do ano: 2000-01-01
date.with(TemporalAdjusters.firstDayOfYear());
Testabilidade
● Suporte a utilização j.t.Clock controlados
○ Mocks
○ Fixos
○ Timezones específicos
● Testes independentes de timezone
● j.t.Clock pode ser injetado
● Trabalhar com datas e horas ficou testável
Resumo
● LocalDate 2014-05-17
● LocalTime 15:29:33
● LocalDateTime 2014-05-17T15:29:33
● OffsetTime 15:29:33+01:00
● OffsetDateTime 2014-05-17T15:29:33+01:00
● ZonedDateTime 2014-05-17T15:29:33+01:00
America/Sao_Paulo
● Year 2014
● YearMonth 2014-05
● MonthDay 05-17
● Instant 2343545656.534 epoch-seconds
Interoperabilidade
Interagindo com a API antiga
java.util java.time
Date Instant
GregorianCalendar ZonedDateTime
TimeZone ZoneId e ZoneOffset
GregorianCalendar (data padrão
1970-01-01)
LocalTime
GregorianCalendar (hora padrão
00:00)
LocalDate
Interoperabilidade
Interoperabilidade
● Calendar.toInstant()
● GregorianCalendar.toZonedDateTime()
● GregorianCalendar.from(ZonedDateTime)
● Date.from(Instant)
● Date.toInstant()
● TimeZone.toZoneId()
JDBC e ORM
Interagindo com o banco de dados
JDBC
● JDBC no Java 8 suporta os novos tipos sem
mudanças na API pública
● getObject e setObject
ANSI SQL Java SE 8
DATE LocalDate
TIME LocalTime
TIMESTAMP LocalDateTime
TIME WITH TIMEZONE OffsetTime
TIMESTAMP WITH TIMEZONE OffsetDateTime
JDBC
JPA
● Ainda sem suporte oficial aos novos tipos
○ https://java.net/jira/browse/JPA_SPEC-63
● Necessário criação de conversores
JPA
public class LocalDateConverter
implements AttributeConverter<LocalDate, Date>
{
@Override
public Date convertToDatabaseColumn(LocalDate ld) {
...
}
@Override
public LocalDate convertToEntityAttribute(Date d) {
...
}
}
JPA
@Override
public Date convertToDatabaseColumn(LocalDate ld) {
if (ld == null) {
return null;
}
return new Date(ld.getYear() - 1900,
ld.getMonthValue() - 1,
ld.getDayOfMonth());
}
JPA
@Override
public LocalDate convertToEntityAttribute(Date d) {
if (d == null) {
return null;
}
return LocalDate.of(d.getYear() + 1900,
d.getMonth() + 1,
d.getDate());
}
Backport
● Suporte ao Java 7
● Backport de funcionalidades
○ Qualidade de APIs muito superior
○ Migração para Java 8 facilitada
○ Não necessariamente de implementação
● threetenbp
○ https://github.com/ThreeTen/threetenbp
Links
● API e tutorial oficial
○ http://docs.oracle.
com/javase/8/docs/api/java/time/package-summary.
html
○ http://docs.oracle.com/javase/tutorial/datetime/
● Projeto threeten-extra
○ https://github.com/ThreeTen/threeten-extra
● Demos e exemplos
○ https://github.com/mgraciano/tdc-2014
Obrigado
@klausboeing
@mgraciano

Finalmente java sabe trabalhar com data e hora

  • 1.
    Habēmus Java 8 FinalmenteJava sabe trabalhar com datas e horários
  • 2.
    Por que umanova API? public boolean isMesNatal(Calendar calendar){ return calendar.get(Calendar.MONTH) == 11; }
  • 3.
    public boolean isMesNatal(Calendarcalendar){ return calendar.get(Calendar.MONTH) == 11; } Por que uma nova API? Dezembro == 11
  • 4.
    Por que umanova API? Calendar dataNascimento = Calendar.getInstance(); dataNascimento.set(1983, Calendar.NOVEMBER, 15); Pessoa pessoa = new Pessoa(dataNascimento); //Afirmação válida assert pessoa.getDataNascimento() .get(Calendar.DAY_OF_MONTH) == 15;
  • 5.
    Por que umanova API? Calendar dataNascimento = Calendar.getInstance(); dataNascimento.set(1983, Calendar.NOVEMBER, 15); Pessoa pessoa = new Pessoa(dataNascimento); pessoa.getDataNascimento().add(Calendar.DAY_OF_MONTH, 10); //Afirmação inválida assert pessoa.getDataNascimento() .get(Calendar.DAY_OF_MONTH) == 15; Calendar é mutável
  • 6.
    Por que umanova API? public class Pessoa{ private Calendar dataNascimento; // encapsulada public Pessoa(Calendar dataNascimento){ this.dataNascimento = dataNascimento; } public Calendar getDataNascimento() { return (Calendar) this.dataNascimento.clone(); } }
  • 7.
    Por que umanova API? long duracao = turno.getDuracao(); // horas? minutos? milisegundos?
  • 8.
    Por que umanova API? public class Turno { /** * @return duração de um turno de * trabalho em milisegundos */ public long getDuracao(){ … } }
  • 9.
    Evolução 1996 - java.util.Date(JDK 1.0) 1997 - java.util.Calendar (JDK 1.1) 2005 - Joda-Time (third library) 2007 - JSR-310
  • 10.
    JSR 310 ● Iníciooficial em 30/01/2007 ● Líderes ○ Stephen Colebourne ○ Michael Nascimento Santos ○ Roger Riggs ● Baseada fortemente no Joda Time ○ http://blog.joda.org/2009/11/why-jsr-310-isn-joda- time_4941.html
  • 11.
  • 12.
    Princípios fundamentais ● Imutável ●Modelo rico, compreensível e fluente ● Separação de cronologias
  • 13.
    Rico modelo de dados Explorandoalguns dos novos tipos de dados disponíveis
  • 14.
    Datas ● LocalDate ○ Datasconsistêm em dia, mês e ano ○ Data de nascimento, feriado, emissão de NF LocalDate.of(2014, Month.MAY, 17);
  • 15.
    Horas ● LocalTime ○ Horáriosconsitêm em hora, minutos e segundos ○ Horário de início do expediente, horário do despertador LocalTime.of(13, 10);
  • 16.
    Datas e horas ●LocalDateTime ○ Composto por data e horas ○ Data e hora de um atendimento médico, entrada de log, marcação de ponto LocalDateTime.of(2014, Month.MAY, 17, 13, 10);
  • 17.
    Mais modelos ● YearMonth ○ano e mês de alistamento militar ● MonthDay ○ mês e dia de nascimento ● Year ○ ano de fabricação de um automóvel ● Instant ○ um ponto na linha do tempo ○ remete à classe j.u.Date
  • 18.
    Mais modelos ● DayOfWeek ○enum com os dias da semana, SUNDAY, MONDAY.. ● Month ○ enum com os meses do ano JANUARY, FEBRUARY ● ZonedDateTime ○ Time-zones são tratadas separadamente ○ Data e hora em um determinado time-zone ■ Remete à classe java.util.Calendar
  • 19.
    A partir doJava 8 será muito importante a escolha correta do tipo de dado baseado na necessidade de cada aplicação.
  • 20.
    Formatação e Parsing ●LocalDate.now().format(...) ● LocalDate.parse(...) ● Resolve o problema de thread-safety da API atual
  • 21.
    Períodose durações ● Period ○Montante de tempo em termos de dias, meses e anos ■ 2 anos, 5 meses e 7 dias ● Duration ○ Montante de tempo em termos de tempo ■ 36 segundos ■ 5 horas ■ Porém suporta o conceito de dias com 24 horas
  • 22.
    Adjusters ● Usado paraalterações complexas ○ ajustar uma data para o último dia do mês ○ ajustar uma data para o proximo dia útil public interface TemporalAdjuster { Temporal adjustInto(Temporal entrada); } LocalDate dataAjustada = data.with(ultimoDiaDoMes()); LocalDate dataAjustada = data.with(proximoDiaUtil());
  • 23.
    Adjusters // 2000-10-15, domingo LocalDatedate = LocalDate.of(2000, Month.OCTOBER, 15); // primeiro dia do mês: 2000-10-01 date.with(TemporalAdjusters.firstDayOfMonth()); // Primeira segunda do mês: 2000-10-02 date.with(TemporalAdjusters.firstInMonth( DayOfWeek.MONDAY)); // último dia do mês: 2000-10-31 date.with(TemporalAdjusters.lastDayOfMonth());
  • 24.
    Adjusters // primeiro diado próximo mês: 2000-11-01 date.with(TemporalAdjusters.firstDayOfNextMonth()); // primeiro dia do próximo ano: 2001-01-01 date.with(TemporalAdjusters.firstDayOfNextYear()); // primeiro dia do ano: 2000-01-01 date.with(TemporalAdjusters.firstDayOfYear());
  • 25.
    Testabilidade ● Suporte autilização j.t.Clock controlados ○ Mocks ○ Fixos ○ Timezones específicos ● Testes independentes de timezone ● j.t.Clock pode ser injetado ● Trabalhar com datas e horas ficou testável
  • 26.
    Resumo ● LocalDate 2014-05-17 ●LocalTime 15:29:33 ● LocalDateTime 2014-05-17T15:29:33 ● OffsetTime 15:29:33+01:00 ● OffsetDateTime 2014-05-17T15:29:33+01:00 ● ZonedDateTime 2014-05-17T15:29:33+01:00 America/Sao_Paulo ● Year 2014 ● YearMonth 2014-05 ● MonthDay 05-17 ● Instant 2343545656.534 epoch-seconds
  • 27.
  • 28.
    java.util java.time Date Instant GregorianCalendarZonedDateTime TimeZone ZoneId e ZoneOffset GregorianCalendar (data padrão 1970-01-01) LocalTime GregorianCalendar (hora padrão 00:00) LocalDate Interoperabilidade
  • 29.
    Interoperabilidade ● Calendar.toInstant() ● GregorianCalendar.toZonedDateTime() ●GregorianCalendar.from(ZonedDateTime) ● Date.from(Instant) ● Date.toInstant() ● TimeZone.toZoneId()
  • 30.
    JDBC e ORM Interagindocom o banco de dados
  • 31.
    JDBC ● JDBC noJava 8 suporta os novos tipos sem mudanças na API pública ● getObject e setObject
  • 32.
    ANSI SQL JavaSE 8 DATE LocalDate TIME LocalTime TIMESTAMP LocalDateTime TIME WITH TIMEZONE OffsetTime TIMESTAMP WITH TIMEZONE OffsetDateTime JDBC
  • 33.
    JPA ● Ainda semsuporte oficial aos novos tipos ○ https://java.net/jira/browse/JPA_SPEC-63 ● Necessário criação de conversores
  • 34.
    JPA public class LocalDateConverter implementsAttributeConverter<LocalDate, Date> { @Override public Date convertToDatabaseColumn(LocalDate ld) { ... } @Override public LocalDate convertToEntityAttribute(Date d) { ... } }
  • 35.
    JPA @Override public Date convertToDatabaseColumn(LocalDateld) { if (ld == null) { return null; } return new Date(ld.getYear() - 1900, ld.getMonthValue() - 1, ld.getDayOfMonth()); }
  • 36.
    JPA @Override public LocalDate convertToEntityAttribute(Dated) { if (d == null) { return null; } return LocalDate.of(d.getYear() + 1900, d.getMonth() + 1, d.getDate()); }
  • 37.
    Backport ● Suporte aoJava 7 ● Backport de funcionalidades ○ Qualidade de APIs muito superior ○ Migração para Java 8 facilitada ○ Não necessariamente de implementação ● threetenbp ○ https://github.com/ThreeTen/threetenbp
  • 38.
    Links ● API etutorial oficial ○ http://docs.oracle. com/javase/8/docs/api/java/time/package-summary. html ○ http://docs.oracle.com/javase/tutorial/datetime/ ● Projeto threeten-extra ○ https://github.com/ThreeTen/threeten-extra ● Demos e exemplos ○ https://github.com/mgraciano/tdc-2014
  • 39.