Introduction to Working with Dates and Time in Go
Working with dates and time is one of the key tasks in any serious application. Whether it's event logging, calculating timeouts, working with schedules, or analyzing time series, the Go language provides a powerful and elegant toolkit in the standard time package. In this article, we will cover working with dates and time in Go from A to Z: from creating time objects to complex operations with time zones and timers.
Basics: the time.Time structure and creating dates
The central element of the time package is the time.Time structure. It represents a moment in time with nanosecond precision and time zone information.
Getting the current time
The most common scenario is to get the current moment:
package main
import ( "fmt" "time")
func main() { now := time.Now() fmt.Println("Current time:", now)}Creating a specific date
To create a date, the time.Date() function is used. Note: in Go, months are specified using constants (time.January, time.February, etc.) or a number from 1 to 12.
func main() { // March 15, 2025, 14:30:00, UTC specificDate := time.Date(2025, time.March, 15, 14, 30, 0, 0, time.UTC) fmt.Println("Specific date:", specificDate) // Creating with nanoseconds preciseDate := time.Date(2025, 3, 15, 14, 30, 0, 123456789, time.UTC) fmt.Println("Precise date:", preciseDate)}Formatting and parsing dates
Go uses a unique approach to formatting: instead of codes like %Y-%m-%d, you use the reference time Mon Jan 2 15:04:05 MST 2006 (which reads as 01 02 03 04 05 06 07 — month, day, hour, minute, second, year).
Formatting (time → string)
The Format() method converts time to a string according to a given layout:
func main() { now := time.Now() // Standard formats fmt.Println("RFC3339:", now.Format(time.RFC3339)) fmt.Println("Date:", now.Format("2006-01-02")) fmt.Println("Time:", now.Format("15:04:05")) fmt.Println("Full format:", now.Format("02.01.2006 15:04:05")) fmt.Println("With weekday:", now.Format("Mon, 02 Jan 2006"))}Parsing (string → time.Time)
The time.Parse() function parses a string into a time structure. Important: the layout must exactly match the format of the input string.
func main() { // Parsing with a known format dateStr := "2025-03-15 14:30:00" parsed, err := time.Parse("2006-01-02 15:04:05", dateStr) if err != nil { panic(err) } fmt.Println("Parsed:", parsed) // Parsing with time zone dateWithZone := "2025-03-15T14:30:00+03:00" parsedWithZone, _ := time.Parse(time.RFC3339, dateWithZone) fmt.Println("With time zone:", parsedWithZone)}Time arithmetic: intervals and comparisons
The time package provides the Duration type for representing time intervals and methods for arithmetic operations.
Addition and subtraction
func main() { now := time.Now() // Adding 2 hours 30 minutes future := now.Add(2*time.Hour + 30*time.Minute) fmt.Println("In 2.5 hours:", future) // Subtracting 7 days past := now.Add(-7 * 24 * time.Hour) fmt.Println("A week ago:", past) // Using AddDate for calendar dates nextMonth := now.AddDate(0, 1, 0) fmt.Println("In a month:", nextMonth)}Calculating the difference between dates
The Sub() method returns a Duration:
func main() { start := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC) end