Trabalhando com datas

Acho que um dos assuntos que mais causa confusão, depois talvez de goroutines e channels, é a manipulação de datas em Go.

Nesse post vou mostrar como manipular, comparar, formatar e fazer parse de datas em Go.

Para iniciar, vamos “printar” a data atual da forma mais simples possível.

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    fmt.Println(now)
}

Ao executar nosso código, veremos um output parecido com 2022-04-27 05:43:52.821666 -0300 -03 m=+0.00011210, que é formado por:

  • 2022-04-27 – ano-mês-dia
  • 05:43:52.821666 – hora:minuto:segundo.nano segundo
  • -03 – timezone
  • m=+0.00011210Monotonic clock

Formatando

Ok, agora que entendemos os componentes da data, vamos fazer uma formatação para exibir de uma forma mais humana e nos padrões que costumamos utilizar no Brasil.

fmt.Println(now.Format("02/01/2006 03:04:05"))

Agora, ao executar nosso código novamente teremos um output parecido com 27/04/2022 05:53:04.

Nesse ponto, provavelmente você está se perguntando de onde eu tirei esses valores que coloquei dentro do método Format.

Diferente da maioria das outras linguagens, Go oferece uma “sequência” de “1 até 7” como parâmetros para formatação da datas, onde:

  • 01 ou 1 = mês
  • 02 ou 2 = dia
  • 03 ou 3 = hora (você também pode usar 15 para representar 24h)
  • 04 ou 4 = minuto
  • 05 ou 5 = segundo
  • 06 = ano (2006 para exibir com 4 dígitos)
  • -07 ou -0700 = timezone

Voltando agora para a struct time.Time, que é a struct retornada pela função time.Now(), além do método Format que acabamos de ver, essa struct tem um método para cada uma das partes da data.

fmt.Println("dia: ", now.Day())
fmt.Println("mês: ", now.Month())
fmt.Println("ano: ", now.Year())
fmt.Println("hora: ", now.Hour())
fmt.Println("minuto: ", now.Minute())
fmt.Println("segundo: ", now.Second())
tz, _ := now.Zone()
fmt.Println("timezone: ", tz)

Criando manualmente e fazendo Parse

Uma das formas para criar uma data manualmente, é utilizar a função time.Date com os parâmetros “ano”, “mês”, “dia”, “hora”, “minuto”, “segundo”, “nano segundo”, “timezone”.

manual := time.Date(2022, 05, 10, 06, 15, 30, 100, time.Local)
fmt.Println(manual)

//output: 2022-05-10 06:15:30.0000001 -0300 -03

Outra forma seria fazer o parse de uma string.

tstr := "27/04/2022 07:34:45"
parsed, err := time.Parse("02/01/2006 03:04:05", tstr)
if err != nil {
	log.Fatal(err)
}

fmt.Println(parsed)

// output: 2022-04-27 07:34:45 +0000 UTC

No entanto, reparem no output. Se a data realmente estiver sendo salva em UTC, então não temos problemas. Agora, se a data for referente a nossa timezone por exemplo, então a data exibida está “incorreta”.

Para corrigir esse problema, precisamos adicionar a timezone na string e o código de parse da timezone no parâmetro “formato” do método Parse.

tstr := "27/04/2022 07:34:45 -03"
parsed, err := time.Parse("02/01/2006 03:04:05 -07", tstr)
if err != nil {
	log.Fatal(err)
}

fmt.Println(parsed)

// output: 2022-04-27 07:34:45 -0300 -03

Manipulando e comparando

Para incrementar ou decrementar uma data, existem duas formas básicas para se fazer. A primeira consiste em criar uma nova data utilizando todas as informações da data anterior e incrementar/decrementar o valor (dia, mês, ano e etc..).

now := time.Now()

// adiciona 13 dias
manual := time.Date(now.Year(), now.Month(), now.Day()+13, now.Hour(), now.Minute(), now.Second(), now.Nanosecond(), now.Location())
fmt.Println(manual)

A segunda forma é utilizar o método Add da struct time.Time.

now := time.Now()
// adicionar 13 dias
next := now.Add(13 * 24 * time.Hour)
fmt.Println(next)

Mas será que as duas datas ficaram iguais mesmo? Para descobrir isso, vamos utilizar o método Equal da struct time.Time.

now := time.Now()

next := now.Add(13 * 24 * time.Hour)
fmt.Println(next)

manual := time.Date(now.Year(), now.Month(), now.Day()+13, now.Hour(), now.Minute(), now.Second(), now.Nanosecond(), now.Location())
fmt.Println(manual)

fmt.Println(next.Equal(manual))

// output:
// 2022-05-10 06:25:04.389426 -0300 -03 m=+1123200.000084928
// 2022-05-10 06:25:04.389426 -0300 -03
// true

Além do método Equal, a struct time.Time também oferece os métodos Before (para ver se a data é anterior) e After (para ver se a data é posterior).

Os três métodos recebem somente um parâmetro, que é a data com o qual a comparação está sendo feita.

Espero que tenham gostado.

Deixem suas dúvidas nos comentários.

Até a próxima!


Subscreva

Fique por dentro de tudo o que acontece no mundo Go.

Deixe uma resposta