Classes de Data
Classes de data
Trabalhar com datas na linguagem Java é uma jornada que inicialmente pode parecer um tanto complexa.
Classes de Data
Um calendário é um sistema que permite medir e representar graficamente o passar do tempo. Com origem etimológica no vocábulo latino calendarium, o calendário recorre à divisão temporária em unidades como anos, meses, semanas e dias.
Este calendário, instaurado pelo papa Gregório XIII em 1582, divide o ano em doze meses, compostos por sua vez entre 28 a 31 dias conforme o caso. O ano do calendário gregoriano começa a 1 de Janeiro e termina a 31 de Dezembro.
Outros calendários são o calendário juliano (que regia até à implementação do gregoriano), o calendário hebreu (também chamado de calendário judaico e qual é usado dentro do judaísmo), o calendário chinês e o calendário muçulmano, os quais se baseiam em diversos dados astronômicos.
O mais fascinante na linguagem Java é a estruturação de classes que representam perfeitamente esta classificação do tempo.
Vamos apresentar as classes que você não poderá deixar de conhecer:
java.util.Calendar
A classe Calendar é uma classe abstrata que representa um instante de tempo distribuída em ANO, MES, DIA, HORA, MINUTO, SEGUNDO e MILISSEGUNDO.
Para criar uma instância de Calendar na sua aplicação, é necessário executar o método estático Calendar.getInstance()
retornando um objeto do tipo java.util.GregorianCalendar
.
java.util.GregorianCalendar[time=1677545679000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,
zone=sun.util.calendar.ZoneInfo[id="America/Sao_Paulo",offset=-10800000,
dstSavings=0,useDaylight=false,transitions=93,lastRule=null],firstDayOfWeek=1,
minimalDaysInFirstWeek=1,
ERA=1,YEAR=2023,MONTH=1,WEEK_OF_YEAR=9,WEEK_OF_MONTH=5,DAY_OF_MONTH=27,DAY_OF_YEAR=58,DAY_OF_WEEK=2,
DAY_OF_WEEK_IN_MONTH=4,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=54,SECOND=39,
MILLISECOND=0,ZONE_OFFSET=-10800000,DST_OFFSET=0]
O primeiro ponto relevante de um calendário é que ele retorna objetos que representam data e hora na aplicação, e este objeto é do tipo java.util.Date
.
public class CalendarApp {
public static void main(String[] args) {
Calendar agora = Calendar.getInstance();
Date data = agora.getTime();
System.out.println(data);
// Mon Feb 27 22:04:29 BRT 2023
}
}
Mas se é mais comum utilizar Date ao invés de Calender, quando instanciar Calendar faz sentido no dia-a-dia? E a resposta é: Quando você precisa realizar alterações no tempo ou obter informações de forma isolada, exemplo:
Vamos imaginar que com base no instante atual você gostaria aumentar em 30 dias e zerar os campos hora, minuto e segundo ?
public class CalendarApp {
public static void main(String[] args) {
Calendar agora = Calendar.getInstance();
//adicionado um mês
agora.add(Calendar.MONTH,1);
//ou adicionando 30 dias corridos
//agora.add(Calendar.DAY_OF_MONTH,30);
//set = definir valores
agora.set(Calendar.HOUR,0);
agora.set(Calendar.MINUTE,0);
agora.set(Calendar.SECOND,0);
//são necessários, afinal o tempo é muiiiito específico
agora.set(Calendar.MILLISECOND,0);
agora.set(Calendar.AM_PM, Calendar.AM);
System.out.println(agora.getTime());
//Obtem o ano, dia do mês e semana do mês respectivamente
System.out.println(calendar.get(Calendar.YEAR));
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
System.out.println(calendar.get(Calendar.WEEK_OF_MONTH));
}
}
set
) mês em um calendar:calendar.set(Calendar.MONTH,6);
// aqui será Julio e não Junho, pois mês em Calendar começa com zero (0)
Sabemos que manipular o tempo exige uma certa pré-definição de valores, afinal não existem mês 13, dia 32, hora 25 e etc.
Por isso, quando for manipular um calendário com base em fluxo de repetição onde um campo não deva modificar outro campo, opte por usar o método roll
ao invés do add
conforme ilustração abaixo:
public class CalendarApp {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime());
//executa primeiro com esta linha
calendar.add(Calendar.SECOND,65);
//em seguida, comente a linha acima
//e execute a linha abaixo
//calendar.roll(Calendar.SECOND,65);
System.out.println(calendar.getTime());
//Mon Feb 27 22:48:23 BRT 2023
//Mon Feb 27 22:48:28 BRT 2023
}
}
java.util.GregorianCalendar
GregorianCalendar é uma implementação concreta da classe abstrata java.util.Calendar
. Não surpreendentemente, o calendário gregoriano é o calendário civil mais utilizado no mundo.
Existem duas opções disponíveis para obter uma instância de GregorianCalendar: Calendar.getInstance()
e usar um dos construtores.
Calendar.getInstance()
não é uma abordagem recomendada, pois retornará uma instância subjetiva para a localidade padrão.public class CalendarApp {
public static void main(String[] args) {
GregorianCalendar gregorianCalendar = new GregorianCalendar();
System.out.println(gregorianCalendar.getTime());
//05 de março de 2023 00:00:00 (lembra que o mês começa com zero)
gregorianCalendar = new GregorianCalendar(2023, 2, 5);
System.out.println(gregorianCalendar.getTime());
//05 de março de 2023 23:17:14 (lembra que o mês começa com zero)
gregorianCalendar = new GregorianCalendar(2023, 2, 5, 23, 17, 14);
System.out.println(gregorianCalendar.getTime());
/*
Resultado no console respectivamente
Tue Feb 28 09:40:51 BRT 2023
Sun Mar 05 00:00:00 BRT 2023
Sun Mar 05 23:17:14 BRT 2023
*/
}
}
Fuso horário
Devemos levar em consideração que exibir data e hora também devemos nos preocupar com a localização relacionada ao meridiano.
No Brasil, existem 4 fusos horários e estão localizados a oeste do Marco Zero (Meridiano de Greenwich), incluindo as ilhas oceânicas e variando de duas a cinco horas a menos em relação ao meridiano principal. Como são medidos a partir de Greenwich, os fusos do Brasil são os fusos -2 GMT, -3 GMT, -4 GMT e -5 GMT, sendo o fuso -3 GMT o Horário Oficial de Brasília.
public class CalendarApp {
public static void main(String[] args) {
GregorianCalendar gregorianCalendar = new GregorianCalendar();
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
int f = 5;
while(f>=2){
formatter.setTimeZone(TimeZone.getTimeZone("GMT-" + f--));
System.out.println(formatter.format(gregorianCalendar.getTime()));
}
}
/*
2023-02-28 09:54:07 GMT-05:00
2023-02-28 10:54:07 GMT-04:00
2023-02-28 11:54:07 GMT-03:00
2023-02-28 12:54:07 GMT-02:00
*/
java.util.Date
A classe Date é a representação fiel de uma data na linguagem Java, após explorarmos Calendar e GregorianCalender, é necessário estar convicto que tudo tem a finalidade de retornar uma data em nossa aplicação.
public class CalendarApp {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
GregorianCalendar gregorianCalendar = new GregorianCalendar();
Date dateCalendar = calendar.getTime();
Date dateGregorianCalender = gregorianCalendar.getTime();
Date dateDefault = new Date();
//evite usar
Date date = new Date(2023,3,1);
System.out.println(dateDefault.getTime());
//retorna um número longo representado em milissegundos
}
}
java.text.DateFormat
A classe DateFormat é responsável por formatar objetos do tipo Date considerando um padrão baseado na localização (locale) da aplicação.
Para criar uma instãncia de NumberFormat é necessário executar alguns de seus métodos de inicialização.
DateFormat.getDateInstance()
-> Retorna um formatador de data exibindo somente dia, mês e ano de acordo com sua localização.DateFormat.getTimeInstance()
-> Retorna um formatador de data exibindo somente hora, minuto e segundo de acordo com sua localização.DateFormat.getDateTimeInstance()
-> Retorna um formatador de data\hora de acordo com sua localização.
public class CalendarApp {
public static void main(String[] args) {
//iniciando um formatador de datas
DateFormat formatador = DateFormat.getDateInstance();
//criando um objeto calendar
Calendar calendario = Calendar.getInstance();
//Obtendo o objeto date para ser formatado
Date data = calendario.getTime();
System.out.println("Formato original da data é: " + data);
//Usando um formatador para exibir a data formatada
String dataFormatada = formatador.format(data);
System.out.println("A data formatada é: " + dataFormatada);
/*
Formato original da data é: Tue Feb 28 13:33:34 BRT 2023
A data formatada é: 28 de fev. de 2023
*/
}
}
Estilos de formatação
Já pensou que você tenha a necessidade de exibir a mesma data com estilos diferentes?
Exemplo de uma data\hora explorando os estilos de formatação pré-definidos.
Data\hora: 28/02/2023 13:55:17
Estilo | Resultado |
---|---|
FULL | terça-feira, 28 de fevereiro de 2023 13:55:17 Horário Padrão de Brasília |
LONG | 28 de fevereiro de 2023 13:55:17 BRT |
MEDIUM | 28 de fev. de 2023 13:55:17 |
SHORT | 28/02/2023 13:55 |
public class CalendarApp {
public static void main(String[] args) {
Calendar calendario = new GregorianCalendar(2023,1,28,13,55,17);
for(int estilo=0; estilo<=3; estilo++){
String style = estilo==0?"FULL":estilo==1?"LONG":estilo==2?"MEDIUM":"SHORT";
DateFormat formatador = DateFormat.getDateTimeInstance(estilo,estilo);
System.out.println("A data formatada com o estilo: " + style + " é: " + formatador.format(calendario.getTime()));
}
}
}
Formatação por região
Aprendemos que existem quatro estilos de formatação, porém ainda assim gostaríamos de aplicar uma formatação com base no idioma (localização) do usuário. Diante deste cenário, aplicamos a devida formatação considerando uma instância de Locale.
public class CalendarApp {
public static void main(String[] args) {
Calendar calendario = new GregorianCalendar(2023,1,28,13,55,17);
for(int estilo=0; estilo<=3; estilo++){
String style = estilo==0?"FULL":estilo==1?"LONG":estilo==2?"MEDIUM":"SHORT";
Locale locale = Locale.US;
//Locale localeBr = new Locale("pt","BR");
DateFormat formatador = DateFormat.getDateTimeInstance(estilo,estilo, locale);
System.out.println("A data formatada com o estilo: " + style + " é: " + formatador.format(calendario.getTime()));
/*
A data formatada com o estilo: FULL é: Tuesday, February 28, 2023 at 1:55:17 PM Brasilia Standard Time
A data formatada com o estilo: LONG é: February 28, 2023 at 1:55:17 PM BRT
A data formatada com o estilo: MEDIUM é: Feb 28, 2023, 1:55:17 PM
A data formatada com o estilo: SHORT é: 2/28/23, 1:55 PM
*/
}
}
}
java.text.SimpleDateFormat
Já pensou agora o usuário solicitar que uma mesma data fosse apresentada conforme abaixo?
Data\hora: 28/02/2023 13:55:17
Solicitação | Exemplo |
---|---|
Ano abreviado | 28/02/23 |
Somente ano-mês | 2023-02 |
Mês legendado abreviado | 28/fev./2023 |
Mês legendado completo | 28/fevereiro/2023 |
public class CalendarApp {
public static void main(String[] args) {
Calendar calendario = new GregorianCalendar(2023,1,28,13,55,17);
//Ano abreviado
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yy");
System.out.println(simpleDateFormat.format(calendario.getTime()));
//Somente ano e mês
simpleDateFormat = new SimpleDateFormat("yyyy/MM");
System.out.println(simpleDateFormat.format(calendario.getTime()));
//Mês legendado abreviado
simpleDateFormat = new SimpleDateFormat("dd/MMM/yyyy");
System.out.println(simpleDateFormat.format(calendario.getTime()));
//Mês legendado completo
simpleDateFormat = new SimpleDateFormat("dd/MMMM/yyyy");
System.out.println(simpleDateFormat.format(calendario.getTime()));
}
}
parse
) string para datas ?Letra | Campo | Exemplo |
---|---|---|
G | Era designator | AD |
y | Year | 2018 (yyyy), 18 (yy) |
M | Month in year | July (MMMM), Jul (MMM), 07 (MM) |
w | Results in week in year | 16 |
W | Results in week in month | 3 |
D | Gives the day count in the year | 266 |
d | Day of the month | 09 (dd), 9(d) |
F | Day of the week in month | 4 |
E | Day name in the week | Tuesday, Tue |
u | Day number of week | where 1 represents Monday, 2 represents Tuesday and so on |
a | AM or PM marker | AM |
H | Hour in the day | (0-23) 12 |
k | Hour in the day | (1-24) 23 |
K | Hour in am/pm | for 12 hour format (0-11) 0 |
h | Hour in am/pm | for 12 hour format (1-12) 12 |
m | Minute in the hour | 59 |
s | Second in the minute | 35 |
S | Millisecond in the minute | 978 |
z | Timezone Pacific Standard | Time; PST; GMT-08:00 |
Z | Timezone offset in hours (RFC pattern) | -0800 |
X | Timezone offset in ISO format | -08; -0800; -08:00 |