Parsing de Strings de Tempo
Parte da seção Lógica & Fluxo do Journey de GO da Coddy. Lição 61 de 68.
Às vezes, você receberá informações de data e hora como strings que precisam ser convertidas em objetos time.Time para processamento. O Go fornece a função time.Parse para lidar com essa conversão.
A função time.Parse funciona como o inverso da formatação - ela recebe uma string de layout e uma string de tempo, então retorna um objeto time.Time:
dateString := "2023-10-26"
parsedTime, err := time.Parse("2006-01-02", dateString)
if err != nil {
fmt.Println("Error parsing time:", err)
} else {
fmt.Println(parsedTime)
}Assim como na formatação, você usa os mesmos componentes de data de referência em sua string de layout. O layout "2006-01-02" diz ao Go para esperar a string de entrada no formato YYYY-MM-DD. O layout deve corresponder ao formato exato da sua string de entrada.
Lembre-se de que time.Parse retorna dois valores: o objeto time.Time analisado e um erro. Sempre verifique o erro para garantir que a análise foi bem-sucedida, pois strings de data inválidas ou layouts incompatíveis farão com que a análise falhe.
Desafio
FácilCrie um analisador de arquivos de log que converta strings de timestamp de vários formatos em objetos time.Time para análise. Este desafio testará sua capacidade de usar time.Parse com diferentes padrões de layout para lidar com vários formatos de data e hora normalmente encontrados em logs de sistema.
Observação importante: Como as mensagens de log e os padrões de layout podem conter espaços, você precisará usar bufio.Scanner para ler linhas de entrada completas. A função fmt.Scanln para de ler no primeiro espaço, o que interromperia entradas de log e layouts com espaços. Use bufio.NewScanner(os.Stdin) e chame scanner.Scan() seguido de scanner.Text() para ler linhas completas.
Você receberá duas entradas:
- Uma string contendo entradas de log no formato
"timestamp1:message1,timestamp2:message2,timestamp3:message3"(por exemplo,"2023-10-26:System startup,2023/12/25:Holiday shutdown,Jan 15 2024:Maintenance window") - Uma string contendo padrões de layout separados por vírgulas no formato
"layout1,layout2,layout3"(por exemplo,"2006-01-02,2006/01/02,Jan 2 2006")
Sua tarefa é:
- Usar
bufio.Scannerpara ler as linhas de entrada corretamente e lidar com espaços nas mensagens de log e nos padrões de layout - Analisar a primeira entrada dividindo-a nas vírgulas para obter entradas de log individuais
- Para cada entrada de log, dividi-la nos dois-pontos para extrair a string de timestamp e a mensagem
- Analisar a segunda entrada dividindo-a nas vírgulas para obter os padrões de layout
- Exibir o cabeçalho da aplicação:
"=== LOG TIMESTAMP PARSER ===" - Exibir o status da análise:
"Processing log entries with multiple timestamp formats..." - Para cada entrada de log, tentar analisar o timestamp usando cada padrão de layout até que um deles funcione:
- Tentar cada padrão de layout com
time.Parseaté que a análise seja bem-sucedida (sem erro) - Quando for bem-sucedida, exibir:
"Parsed: [timestamp_string] -> [parsed_time_object] (using layout: [successful_layout])" - Também exibir:
" Message: [log_message]" - Se nenhum layout funcionar para um timestamp, exibir:
"Failed to parse: [timestamp_string] - no matching layout found"
- Tentar cada padrão de layout com
- Após processar todas as entradas, exibir as estatísticas da análise:
"=== PARSING RESULTS ===""Total log entries processed: [number_of_entries]""Successfully parsed timestamps: [number_of_successful_parses]""Failed parsing attempts: [number_of_failed_parses]"
- Exibir as estatísticas de uso dos layouts:
"Layout pattern usage:"- Para cada padrão de layout:
" [layout_pattern]: [number_of_times_used] times"
- Se algum timestamp tiver sido analisado com sucesso, exibir a análise cronológica:
"=== CHRONOLOGICAL ANALYSIS ===""Earliest timestamp: [earliest_parsed_time]""Latest timestamp: [latest_parsed_time]""Time span covered: [time_difference_description]"
- Exibir a mensagem de conclusão:
"Log parsing completed - timestamps converted to time objects"
Use o pacote time para as operações de análise, o pacote strings para dividir as strings de entrada, os pacotes bufio e os para o tratamento adequado da entrada e o pacote fmt para a saída formatada. Lembre-se de que time.Parse retorna tanto um objeto time.Time quanto um erro — você deve verificar o erro para determinar se a análise foi bem-sucedida. Quando a análise falhar com um layout, tente o próximo padrão de layout até encontrar um que funcione ou esgotar todas as opções. Este desafio demonstra como lidar com vários formatos de timestamp em cenários reais de processamento de logs.
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strings"
"time"
)
func main() {
// Cria um scanner para ler as linhas de entrada
scanner := bufio.NewScanner(os.Stdin)
// Lê as entradas de log
scanner.Scan()
logEntries := scanner.Text()
// Lê os padrões de layout
scanner.Scan()
layoutPatterns := scanner.Text()
// Analisa as entradas
entries := strings.Split(logEntries, ",")
layouts := strings.Split(layoutPatterns, ",")
// Inicializa contadores para estatísticas
totalEntries := len(entries)
successfulParses := 0
failedParses := 0
layoutUsage := make(map[string]int)
var parsedTimes []time.Time
// TODO: Escreva seu código abaixo
// 1. Exibir o cabeçalho da aplicação
// 2. Exibir o status de processamento
// 3. Processar cada entrada de log:
// - Dividir a entrada em ":" para obter o timestamp e a mensagem
// - Tentar cada padrão de layout até que um funcione
// - Exibir os resultados da análise
// - Atualizar as estatísticas
// 4. Exibir estatísticas de análise
// 5. Exibir estatísticas de uso de layout
// 6. Se os timestamps foram analisados, exibir análise cronológica
// 7. Exibir mensagem de conclusão
}Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Lógica & Fluxo
1Fluxo de Controle Avançado
Switch com `fallthrough`Interrompendo Loops AninhadosContinuando um Loop EspecíficoA Instrução `goto`Recapitulação - Controle de Loop Avançado4Projeto: Lista de Tarefas Simples
Configuração do ProjetoAdicionando uma Tarefa7Tratamento de Erros em Profundidade
Tipos de Erro PersonalizadosWrapping de Erros com `%w`Unwrapping com `errors.Is`Unwrapping com `errors.As`Entendendo o `panic`Usando o `recover`Recapitulação - Divisão Segura10Trabalhando com Tempo
Obtendo o Horário AtualCriando um Horário EspecíficoFormatando o TempoParsing de Strings de TempoDuração de TempoAritmética de TempoSleep e TickersRecapitulação - Timer Simples2Structs e Métodos
Definindo Métodos em StructsRecebedores de ValorRecebedores de PonteiroEscolhendo RecebedoresMétodos vs FunçõesRecapitulação - Comportamento de Structs5Mapas em Profundidade
Mapas de StructsPonteiros como Valores de MapVerificando Mapas NilComparando MapasRecapitulação - Contador de Frequência de Palavras3Interfaces (O Básico)
O que é uma Interface?Definindo uma InterfaceImplementando uma InterfaceUsando Tipos de InterfaceInterface VaziaAsserções de TipoType SwitchRecapitulação - Formas e ComportamentosPratique por conta própria: Compilador de Go online