💻 Exemplos: Capítulo 07: Manipulação Moderna de Datas e Horas: API java.time, Timezones, Períodos e Formatação
Especialização em Sistemas com Java 21 LTS • Capítulo 07
🎯 Visão Geral dos Exemplos Práticos
Neste laboratório prático, implementaremos exemplos corporativos completos explorando:
- Motor de Vencimento e Juros de Boletos: ajuste automático para dias úteis bancários com
TemporalAdjusterse cálculo de atraso comChronoUnit. - Central de Operações Globais (NOC Multi-Fuso): conversão de carimbos
Instantem horários locais para polos internacionais (SP, Nova York, Londres e Tóquio). - Formatação Thread-Safe e Internacionalizada: parsing e formatação padrão ISO e formato nacional brasileiro.
💻 Exemplo 01 — Calculadora Financeira de Vencimentos e Juros de Mora
package com.empresa.tempo;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
/**
* Calculadora bancária de faturamento e liquidação em dias úteis.
*/
public class CalculadoraBoletoBancario {
public static final DateTimeFormatter FORMATO_BR = DateTimeFormatter.ofPattern("dd/MM/yyyy");
public static final BigDecimal MULTA_ATRASO_PERCENTUAL = new BigDecimal("0.02"); // 2%
public static final BigDecimal JUROS_DIARIOS_PERCENTUAL = new BigDecimal("0.00033"); // 0.033% ao dia
public record TituloCobranca(
String idTitulo,
BigDecimal valorNominal,
LocalDate dataEmissao,
LocalDate dataVencimentoOriginal
) {
public LocalDate calcularVencimentoUtil() {
DayOfWeek dia = dataVencimentoOriginal.getDayOfWeek();
if (dia == DayOfWeek.SATURDAY) {
return dataVencimentoOriginal.plusDays(2); // Prorroga para Segunda
} else if (dia == DayOfWeek.SUNDAY) {
return dataVencimentoOriginal.plusDays(1); // Prorroga para Segunda
}
return dataVencimentoOriginal;
}
public BigDecimal calcularValorLiquidacao(LocalDate dataPagamento) {
LocalDate vencimentoEfetivo = calcularVencimentoUtil();
if (!dataPagamento.isAfter(vencimentoEfetivo)) {
return valorNominal; // Sem encargos
}
long diasAtraso = ChronoUnit.DAYS.between(vencimentoEfetivo, dataPagamento);
BigDecimal multa = valorNominal.multiply(MULTA_ATRASO_PERCENTUAL);
BigDecimal juros = valorNominal.multiply(JUROS_DIARIOS_PERCENTUAL).multiply(new BigDecimal(diasAtraso));
return valorNominal.add(multa).add(juros).setScale(2, RoundingMode.HALF_UP);
}
}
public static void main(String[] args) {
System.out.println("================================================================================");
System.out.println(" SISTEMA BANCÁRIO: CÁLCULO DE VENCIMENTOS E MORA (JAVA 21) ");
System.out.println("================================================================================");
// Título que vence em um Domingo
LocalDate emissao = LocalDate.of(2026, 10, 1);
LocalDate vencimentoDomingo = LocalDate.of(2026, 10, 18); // Domingo
TituloCobranca titulo = new TituloCobranca("FAT-2026-9081", new BigDecimal("1500.00"), emissao, vencimentoDomingo);
LocalDate vencimentoAjustado = titulo.calcularVencimentoUtil();
System.out.printf("📄 Título: %s | Valor: R$ %.2f%n", titulo.idTitulo(), titulo.valorNominal());
System.out.printf(" Emissão : %s%n", titulo.dataEmissao().format(FORMATO_BR));
System.out.printf(" Vencimento Nominal : %s (%s)%n",
titulo.dataVencimentoOriginal().format(FORMATO_BR), titulo.dataVencimentoOriginal().getDayOfWeek());
System.out.printf(" Vencimento Efetivo : %s (%s) [Prorrogação Bancária]%n%n",
vencimentoAjustado.format(FORMATO_BR), vencimentoAjustado.getDayOfWeek());
// Simulação 1: Pagamento na segunda-feira prorrogada (Isento de encargos)
LocalDate dataPgto1 = LocalDate.of(2026, 10, 19);
BigDecimal valor1 = titulo.calcularValorLiquidacao(dataPgto1);
System.out.printf("1. Pagamento em %s: R$ %.2f [SEM ENCARGOS]%n", dataPgto1.format(FORMATO_BR), valor1);
// Simulação 2: Pagamento com 10 dias de atraso após a data prorrogada
LocalDate dataPgto2 = LocalDate.of(2026, 10, 29);
BigDecimal valor2 = titulo.calcularValorLiquidacao(dataPgto2);
System.out.printf("2. Pagamento em %s (10d atraso): R$ %.2f [MULTA + JUROS]%n", dataPgto2.format(FORMATO_BR), valor2);
System.out.println("================================================================================");
}
}
💻 Exemplo 02 — Central de Operações de Rede com Múltiplos Fusos Horários
package com.empresa.tempo;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* Matriz de sincronização horária de eventos críticos em polos internacionais.
*/
public class CentralOperacoesGlobal {
public static final DateTimeFormatter FORMATO_LOG = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss (z)");
public record PoloOperacional(String regiao, ZoneId fuso) {}
public static void main(String[] args) {
System.out.println("================================================================================");
System.out.println(" CENTRAL DE COMANDO NOC: DISPERSÃO HORÁRIA DE INCIDENTE CRÍTICO ");
System.out.println("================================================================================");
// Momento do incidente registrado em tempo universal de máquina (UTC)
Instant instanteAlertaUtc = Instant.now();
System.out.printf("⚠️ INCIDENTE REGISTRADO (UTC Instant): %s%n%n", instanteAlertaUtc);
List<PoloOperacional> centros = List.of(
new PoloOperacional("Brasil (São Paulo / B3)", ZoneId.of("America/Sao_Paulo")),
new PoloOperacional("EUA (Nova York / NYSE)", ZoneId.of("America/New_York")),
new PoloOperacional("Reino Unido (Londres / LSE)", ZoneId.of("Europe/London")),
new PoloOperacional("Japão (Tóquio / TSE)", ZoneId.of("Asia/Tokyo"))
);
System.out.printf("%-26s | %-18s | %s%n", "CENTRO DE COMANDO", "FUSO HORÁRIO", "HORÁRIO LOCAL DO EVENTO");
System.out.println("---------------------------+--------------------+---------------------------------");
for (PoloOperacional polo : centros) {
ZonedDateTime horaLocal = instanteAlertaUtc.atZone(polo.fuso());
System.out.printf("%-26s | %-18s | %s%n",
polo.regiao(), polo.fuso().getId(), horaLocal.format(FORMATO_LOG));
}
System.out.println("================================================================================");
}
}
📋 Resultado Esperado no Console
================================================================================
SISTEMA BANCÁRIO: CÁLCULO DE VENCIMENTOS E MORA (JAVA 21)
================================================================================
📄 Título: FAT-2026-9081 | Valor: R$ 1500.00
Emissão : 01/10/2026
Vencimento Nominal : 18/10/2026 (SUNDAY)
Vencimento Efetivo : 19/10/2026 (MONDAY) [Prorrogação Bancária]
1. Pagamento em 19/10/2026: R$ 1500.00 [SEM ENCARGOS]
2. Pagamento em 29/10/2026 (10d atraso): R$ 1534.95 [MULTA + JUROS]
================================================================================
================================================================================
CENTRAL DE COMANDO NOC: DISPERSÃO HORÁRIA DE INCIDENTE CRÍTICO
================================================================================
⚠️ INCIDENTE REGISTRADO (UTC Instant): 2026-10-15T18:30:00Z
CENTRO DE COMANDO | FUSO HORÁRIO | HORÁRIO LOCAL DO EVENTO
---------------------------+--------------------+---------------------------------
Brasil (São Paulo / B3) | America/Sao_Paulo | 15/10/2026 15:30:00 (-03)
EUA (Nova York / NYSE) | America/New_York | 15/10/2026 14:30:00 (EDT)
Reino Unido (Londres / LSE)| Europe/London | 15/10/2026 19:30:00 (BST)
Japão (Tóquio / TSE) | Asia/Tokyo | 16/10/2026 03:30:00 (JST)
================================================================================