How to Use the Golang Time Package? Code Examples Included

Relia Software

Relia Software

The Go time package offers accurate, timezone-aware, and thread-safe time handling using the Gregorian calendar with monotonic and wall clock support.

Go Time Package

The Go time package provides comprehensive functionality for measuring and displaying time. It follows a design philosophy that prioritizes accuracy, timezone awareness, and thread safety. The package uses a Gregorian calendar with no leap seconds and distinguishes between "wall clock" time (for telling time) and "monotonic clock" time (for measuring time intervals).

Key Design Principles

  • Immutability: time.Time values are immutable; operations return new instances
  • Thread Safety: All time operations are safe for concurrent use
  • Timezone Awareness: Every time.Time has an associated time.Location
  • Precision: Nanosecond precision for all time operations
  • Monotonic Clock Support: Robust time measurement unaffected by clock adjustments

Core Types

time.Time

Represents an instant in time with nanosecond precision. Contains both wall clock and optional monotonic clock readings.

go
type Time struct {
    // Internal fields are unexported
    // wall and ext encode the wall time and optional monotonic reading
}

Key characteristics:

  • Zero value: January 1, year 1, 00:00:00.000000000 UTC
  • Immutable: methods return new Time values
  • Thread-safe for concurrent reads
  • Contains both wall clock and optional monotonic clock readings

time.Duration

Represents elapsed time as an int64 nanosecond count, supporting approximately 290 years.

go
type Duration int64

// Predefined constants
const (
    Nanosecond  Duration = 1
    Microsecond          = 1000 * Nanosecond
    Millisecond          = 1000 * Microsecond
    Second               = 1000 * Millisecond
    Minute               = 60 * Second
    Hour                 = 60 * Minute
)

time.Location

Represents a time zone, mapping time instants to the zone in use at that time.

go
var (
    UTC   *Location = &utcLoc   // UTC timezone
    Local *Location = &localLoc // System's local timezone
)

Time Creation and Current Time

Learn how to get the current time and create specific timestamps using Go’s built-in functions. 

Getting Current Time

go
// Get current time with monotonic clock reading
now := time.Now()
fmt.Println(now) // 2025-08-27 14:55:00.123456789 +0700 +07 m=+0.000000001

// Get current time in specific timezone
loc, _ := time.LoadLocation("America/New_York")
nowNY := time.Now().In(loc)

Creating Specific Times

go
// Create specific time
t := time.Date(2025, time.August, 27, 14, 30, 0, 0, time.UTC)

// From Unix timestamp
unixTime := time.Unix(1693140600, 0) // seconds since epoch
unixMilli := time.UnixMilli(1693140600000) // milliseconds since epoch
unixMicro := time.UnixMicro(1693140600000000) // microseconds since epoch

Zero Time Detection

Detect and handle zero-value time.Time objects safely in your code.

go
var t time.Time
if t.IsZero() {
    fmt.Println("Time is zero value")
}

Golang Time Format and Parse

Go uses a unique reference time approach for formatting: Mon Jan 2 15:04:05 MST 2006 (which can be remembered as 01/02 03:04:05PM '06 -0700).

Predefined Layout Constants

go
const (
    Layout      = "01/02 03:04:05PM '06 -0700"
    ANSIC       = "Mon Jan _2 15:04:05 2006"
    UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
    RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
    RFC822      = "02 Jan 06 15:04 MST"
    RFC822Z     = "02 Jan 06 15:04 -0700"
    RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
    RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
    RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700"
    RFC3339     = "2006-01-02T15:04:05Z07:00"
    RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
    Kitchen     = "3:04PM"
    DateTime    = "2006-01-02 15:04:05"
    DateOnly    = "2006-01-02"
    TimeOnly    = "15:04:05"
)

Formatting Examples

go
now := time.Now()

// Using predefined constants
fmt.Println(now.Format(time.RFC3339))     // 2025-08-27T14:55:00Z
fmt.Println(now.Format(time.Kitchen))     // 2:55PM
fmt.Println(now.Format(time.DateOnly))    // 2025-08-27

// Custom formatting
fmt.Println(now.Format("2006-01-02 15:04:05")) // 2025-08-27 14:55:00
fmt.Println(now.Format("Jan 2, 2006"))         // Aug 27, 2025
fmt.Println(now.Format("Monday, January 2"))    // Tuesday, August 27

Parsing Examples

go
// Parse with predefined layout
t1, err := time.Parse(time.RFC3339, "2025-08-27T14:55:00Z")
if err != nil {
    log.Fatal(err)
}

// Parse with custom layout
t2, err := time.Parse("2006-01-02 15:04:05", "2025-08-27 14:55:00")
if err != nil {
    log.Fatal(err)
}

// Parse in specific location
loc, _ := time.LoadLocation("America/New_York")
t3, err := time.ParseInLocation("2006-01-02 15:04:05", "2025-08-27 14:55:00", loc)

Layout Reference Guide

Component

Options

Example

Year

"2006", "06"

2025, 25

Month

"Jan", "January", "01", "1"

Aug, August, 08, 8

Day

"2", "_2", "02"

27, 27, 27

Weekday

"Mon", "Monday"

Tue, Tuesday

Hour

"15", "3", "03"

14, 2, 02

Minute

"4", "04"

5, 05

Second

"5", "05"

0, 00

Timezone

"-0700", "MST", "Z07:00"

+0700, +07, +07:00

Golang Time Duration Operations

Creating Durations

go
// From constants
d1 := 5 * time.Second
d2 := 2 * time.Minute + 30 * time.Second
d3 := time.Hour + 15 * time.Minute

// From string parsing
d4, err := time.ParseDuration("1h30m45s")
d5, err := time.ParseDuration("100ms")
d6, err := time.ParseDuration("2.5h")

Duration Methods

go
d := 90 * time.Minute

// Convert to different units
fmt.Println(d.Hours())        // 1.5
fmt.Println(d.Minutes())      // 90
fmt.Println(d.Seconds())      // 5400
fmt.Println(d.Milliseconds()) // 5400000
fmt.Println(d.Microseconds()) // 5400000000
fmt.Println(d.Nanoseconds())  // 5400000000000

// String representation
fmt.Println(d.String()) // 1h30m0s

// Absolute value
neg := -5 * time.Second
fmt.Println(neg.Abs()) // 5s

// Rounding and truncation
d := 1*time.Hour + 15*time.Minute + 30*time.Second + 918*time.Millisecond
fmt.Println(d.Round(time.Minute))    // 1h16m0s
fmt.Println(d.Truncate(time.Minute)) // 1h15m0s

Time Zone Handling

Loading Time Zones

go
// Load specific timezone
ny, err := time.LoadLocation("America/New_York")
if err != nil {
    log.Fatal(err)
}

// Load UTC and Local
utc := time.UTC
local := time.Local

// Create fixed timezone
// FixedZone(name, offset_in_seconds)
customTZ := time.FixedZone("GMT+8", 8*60*60)

Converting Between Time Zones

go
// Create time in UTC
utcTime := time.Date(2025, 8, 27, 14, 30, 0, 0, time.UTC)

// Convert to different timezones
ny, _ := time.LoadLocation("America/New_York")
tokyo, _ := time.LoadLocation("Asia/Tokyo")

nyTime := utcTime.In(ny)
tokyoTime := utcTime.In(tokyo)

fmt.Println("UTC:   ", utcTime.Format(time.RFC3339))
fmt.Println("NY:    ", nyTime.Format(time.RFC3339))
fmt.Println("Tokyo: ", tokyoTime.Format(time.RFC3339))

Working with DST

go
// Check if time is in DST
ny, _ := time.LoadLocation("America/New_York")
summer := time.Date(2025, 7, 15, 12, 0, 0, 0, ny)
winter := time.Date(2025, 12, 15, 12, 0, 0, 0, ny)

fmt.Println("Summer DST:", summer.IsDST()) // true
fmt.Println("Winter DST:", winter.IsDST()) // false

// Get timezone information
name, offset := summer.Zone()
fmt.Printf("Zone: %s, Offset: %d seconds\\n", name, offset)

Time Comparison and Arithmetic

Compare two times or calculate differences using Go’s intuitive API.

Time Comparison

go
t1 := time.Date(2025, 8, 27, 10, 0, 0, 0, time.UTC)
t2 := time.Date(2025, 8, 27, 11, 0, 0, 0, time.UTC)

// Comparison methods
fmt.Println(t1.Before(t2))  // true
fmt.Println(t1.After(t2))   // false
fmt.Println(t1.Equal(t2))   // false

// Compare method (Go 1.20+)
fmt.Println(t1.Compare(t2)) // -1 (t1 < t2)
fmt.Println(t2.Compare(t1)) // 1  (t2 > t1)
fmt.Println(t1.Compare(t1)) // 0  (t1 == t1)

// Prefer Equal() over == for reliable comparison
fmt.Println(t1 == t2)    // may be unreliable due to monotonic clock
fmt.Println(t1.Equal(t2)) // reliable comparison

Time Arithmetic

go
now := time.Now()

// Add duration
future := now.Add(2 * time.Hour)
past := now.Add(-30 * time.Minute)

// Add date components
nextYear := now.AddDate(1, 0, 0)    // +1 year
nextMonth := now.AddDate(0, 1, 0)   // +1 month
tomorrow := now.AddDate(0, 0, 1)    // +1 day

// Subtract times to get duration
elapsed := future.Sub(now)
fmt.Println(elapsed) // 2h0m0s

// Helper functions
since := time.Since(now)  // time.Now().Sub(now)
until := time.Until(future) // future.Sub(time.Now())

Rounding and Truncation

go
now := time.Now()

// Round to nearest hour
rounded := now.Round(time.Hour)

// Truncate to start of hour
truncated := now.Truncate(time.Hour)

// Strip monotonic clock reading
stripped := now.Round(0)

Monotonic Clock

The monotonic clock provides accurate time measurement unaffected by system clock adjustments.

Understanding Monotonic Clock

go
// Times from Now() include monotonic reading
start := time.Now()
time.Sleep(100 * time.Millisecond)
end := time.Now()

// Duration calculation uses monotonic clock if available
elapsed := end.Sub(start) // Accurate even if system clock changes

// Monotonic clock visible in String() output
fmt.Println(start) // includes "m=+0.000000001"

Operations That Strip Monotonic Clock

go
now := time.Now() // Has monotonic reading

// These operations strip monotonic reading:
utc := now.UTC()              // Timezone conversion
local := now.Local()          // Timezone conversion
ny := now.In(nyLocation)      // Timezone conversion
rounded := now.Round(time.Hour)    // Rounding (when d > 0)
truncated := now.Truncate(time.Hour) // Truncation (when d > 0)
dated := now.AddDate(0, 0, 1) // Date arithmetic

// Explicitly strip monotonic reading
stripped := now.Round(0)

Monotonic Clock Best Practices

  • Use for measuring elapsed time: elapsed := time.Since(start)
  • Don't rely on monotonic clock for serialization
  • Use t.Equal(u) instead of t == u for comparisons
  • Strip monotonic reading when using as map keys: t.Round(0)

Timers and Tickers

Timers

go
// Simple timer for one-time events
timer := time.NewTimer(5 * time.Second)
<-timer.C // Wait for timer to fire
fmt.Println("Timer fired!")

// Using After for simple delays
select {
case <-time.After(5 * time.Second):
    fmt.Println("Timeout!")
case data := <-dataChannel:
    fmt.Println("Received:", data)
}

// Timer with function callback
timer := time.AfterFunc(5*time.Second, func() {
    fmt.Println("Timer callback executed!")
})

// Stop timer if needed
if !timer.Stop() {
    // Timer already fired or was stopped
}

// Reset timer
timer.Reset(10 * time.Second)

Tickers

go
// Create ticker for repeated events
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop() // Always stop tickers to prevent leaks

for i := 0; i < 5; i++ {
    select {
    case t := <-ticker.C:
        fmt.Printf("Tick at %v\\n", t)
    }
}

// Using Tick for simple repeating events
c := time.Tick(1 * time.Second) // Returns nil if d <= 0
for t := range c {
    fmt.Printf("Tick: %v\\n", t)
    // Note: This creates an unstoppable ticker
}

// Reset ticker period
ticker.Reset(2 * time.Second)

Timer Safety and Performance

go
// Safe timer pattern
func safeTimerPattern() {
    timer := time.NewTimer(5 * time.Second)
    defer func() {
        if !timer.Stop() {
            // Drain channel if timer fired
            select {
            case <-timer.C:
            default:
            }
        }
    }()

    select {
    case <-timer.C:
        fmt.Println("Timer fired")
    case <-someOtherChannel():
        fmt.Println("Other event occurred")
        return
    }
}

>> Read more: A Comprehensive Guide to Concurrency in Golang

Performance Considerations

Timer Resolution

  • Unix systems: ~1ms resolution
  • Windows 1803+: ~0.5ms resolution
  • Older Windows: ~16ms resolution (can be improved with TimeBeginPeriod)

Memory and GC

go
// As of Go 1.23, timers and tickers are automatically GC'd
// No need to explicitly stop them for GC purposes

// However, still stop for logic purposes
ticker := time.NewTicker(time.Second)
defer ticker.Stop() // Good practice for clarity

// Avoid creating many short-lived timers in hot paths
// Consider using a single timer pool or time wheel

Benchmark Example

go
func BenchmarkTimeOperations(b *testing.B) {
    now := time.Now()

    b.Run("Now", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            _ = time.Now()
        }
    })

    b.Run("Format", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            _ = now.Format(time.RFC3339)
        }
    })

    b.Run("Parse", func(b *testing.B) {
        timeStr := "2025-08-27T14:55:00Z"
        for i := 0; i < b.N; i++ {
            _, _ = time.Parse(time.RFC3339, timeStr)
        }
    })
}

Best Practices

Always Handle Parsing Errors

go
// Bad
t, _ := time.Parse(time.RFC3339, userInput)

// Good
t, err := time.Parse(time.RFC3339, userInput)
if err != nil {
    return fmt.Errorf("invalid time format: %w", err)
}

Use Appropriate Layout Constants

go
// Bad - magic strings
t.Format("2006-01-02T15:04:05Z07:00")

// Good - use constants
t.Format(time.RFC3339)

// Good - define custom constants
const CustomLayout = "2006-01-02 15:04:05"
t.Format(CustomLayout)

Be Explicit About Time Zones

go
// Bad - ambiguous timezone
t, _ := time.Parse("2006-01-02 15:04:05", "2025-08-27 14:55:00")

// Good - explicit timezone
loc, _ := time.LoadLocation("America/New_York")
t, _ := time.ParseInLocation("2006-01-02 15:04:05", "2025-08-27 14:55:00", loc)

// Or use timezone-aware format
t, _ := time.Parse(time.RFC3339, "2025-08-27T14:55:00Z")

Use time.Equal() for Comparisons

go
// Bad - may fail due to monotonic clock differences
if t1 == t2 {
    // ...
}

// Good - handles monotonic clock properly
if t1.Equal(t2) {
    // ...
}

Measure Elapsed Time Correctly

go
// Good - uses monotonic clock
start := time.Now()
doWork()
elapsed := time.Since(start)

// Also good
start := time.Now()
doWork()
elapsed := time.Now().Sub(start)

Store UTC in Databases

go
// Good practice - store UTC, display in local timezone
func storeTime(t time.Time) {
    utcTime := t.UTC()
    // Store utcTime in database
}

func displayTime(utcTime time.Time, userTZ string) string {
    loc, _ := time.LoadLocation(userTZ)
    localTime := utcTime.In(loc)
    return localTime.Format("2006-01-02 15:04:05 MST")
}

Handle Zero Times

go
func processTime(t time.Time) error {
    if t.IsZero() {
        return errors.New("time cannot be zero")
    }
    // Process non-zero time
    return nil
}

Use Context for Timeouts

go
func processWithTimeout(ctx context.Context) error {
    ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
    defer cancel()

    // Use ctx for operations that should respect timeout
    return doWorkWithContext(ctx)
}

Common Pitfalls and Solutions

Layout String Confusion

go
// Common mistake - using wrong reference time
t.Format("YYYY-MM-DD") // Wrong! Go doesn't use these placeholders

// Correct - use Go's reference time
t.Format("2006-01-02") // Correct

Time Zone Loading Errors

go
// Bad - ignoring errors
loc, _ := time.LoadLocation("Invalid/Timezone")

// Good - handle errors
loc, err := time.LoadLocation("America/New_York")
if err != nil {
    log.Printf("Failed to load timezone: %v", err)
    loc = time.UTC // fallback to UTC
}

Timer/Ticker Resource Leaks

go
// Bad - potential resource leak
func badTicker() {
    ticker := time.NewTicker(time.Second)
    for range ticker.C {
        // Process tick
        if someCondition {
            return // Ticker never stopped!
        }
    }
}

// Good - always stop tickers
func goodTicker() {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            // Process tick
            if someCondition {
                return
            }
        }
    }
}

Monotonic Clock Stripping

go
// Problem - using time as map key
times := make(map[time.Time]string)
t1 := time.Now()
t2 := time.Date(2025, 8, 27, 14, 55, 0, 0, time.UTC)
// t1 and t2 might represent same time but have different monotonic readings

// Solution - strip monotonic reading
times[t1.Round(0)] = "value1"
times[t2.Round(0)] = "value2"

Parsing Ambiguous Formats

go
// Problem - ambiguous date format
dateStr := "01/02/2006" // Is this Jan 2 or Feb 1?

// Solution - use unambiguous formats
// Use ISO 8601 format
dateStr := "2006-01-02"
t, err := time.Parse("2006-01-02", dateStr)

// Or be explicit about format
t, err := time.Parse("01/02/2006", "01/02/2006") // MM/DD/YYYY
t, err := time.Parse("02/01/2006", "01/02/2006") // DD/MM/YYYY

Examples and Use Cases

API Rate Limiting

go
type RateLimiter struct {
    tokens    int
    maxTokens int
    interval  time.Duration
    lastRefill time.Time
    mu        sync.Mutex
}

func NewRateLimiter(maxTokens int, interval time.Duration) *RateLimiter {
    return &RateLimiter{
        tokens:     maxTokens,
        maxTokens:  maxTokens,
        interval:   interval,
        lastRefill: time.Now(),
    }
}

func (rl *RateLimiter) Allow() bool {
    rl.mu.Lock()
    defer rl.mu.Unlock()

    now := time.Now()
    elapsed := now.Sub(rl.lastRefill)

    if elapsed >= rl.interval {
        rl.tokens = rl.maxTokens
        rl.lastRefill = now
    }

    if rl.tokens > 0 {
        rl.tokens--
        return true
    }

    return false
}

Retry with Exponential Backoff

go
func retryWithBackoff(operation func() error, maxRetries int) error {
    baseDelay := 100 * time.Millisecond
    maxDelay := 10 * time.Second

    for attempt := 0; attempt < maxRetries; attempt++ {
        if err := operation(); err == nil {
            return nil
        }

        if attempt == maxRetries-1 {
            return fmt.Errorf("operation failed after %d attempts", maxRetries)
        }

        // Calculate delay with exponential backoff
        delay := time.Duration(float64(baseDelay) * math.Pow(2, float64(attempt)))
        if delay > maxDelay {
            delay = maxDelay
        }

        time.Sleep(delay)
    }

    return nil
}

Scheduled Task Runner

go
type Scheduler struct {
    tasks map[string]*ScheduledTask
    mu    sync.RWMutex
    stop  chan struct{}
}

type ScheduledTask struct {
    Name     string
    Interval time.Duration
    Fn       func()
    ticker   *time.Ticker
}

func NewScheduler() *Scheduler {
    return &Scheduler{
        tasks: make(map[string]*ScheduledTask),
        stop:  make(chan struct{}),
    }
}

func (s *Scheduler) AddTask(name string, interval time.Duration, fn func()) {
    s.mu.Lock()
    defer s.mu.Unlock()

    task := &ScheduledTask{
        Name:     name,
        Interval: interval,
        Fn:       fn,
        ticker:   time.NewTicker(interval),
    }

    s.tasks[name] = task

    go func() {
        for {
            select {
            case <-task.ticker.C:
                fn()
            case <-s.stop:
                return
            }
        }
    }()
}

func (s *Scheduler) Stop() {
    s.mu.Lock()
    defer s.mu.Unlock()

    close(s.stop)

    for _, task := range s.tasks {
        task.ticker.Stop()
    }
}

Time-based Cache with TTL

go
type TTLCache struct {
    items map[string]*cacheItem
    mu    sync.RWMutex
}

type cacheItem struct {
    value     interface{}
    expiresAt time.Time
}

func NewTTLCache() *TTLCache {
    cache := &TTLCache{
        items: make(map[string]*cacheItem),
    }

    // Start cleanup goroutine
    go cache.cleanup()

    return cache
}

func (c *TTLCache) Set(key string, value interface{}, ttl time.Duration) {
    c.mu.Lock()
    defer c.mu.Unlock()

    c.items[key] = &cacheItem{
        value:     value,
        expiresAt: time.Now().Add(ttl),
    }
}

func (c *TTLCache) Get(key string) (interface{}, bool) {
    c.mu.RLock()
    defer c.mu.RUnlock()

    item, exists := c.items[key]
    if !exists {
        return nil, false
    }

    if time.Now().After(item.expiresAt) {
        return nil, false
    }

    return item.value, true
}

func (c *TTLCache) cleanup() {
    ticker := time.NewTicker(1 * time.Minute)
    defer ticker.Stop()

    for range ticker.C {
        c.mu.Lock()
        now := time.Now()
        for key, item := range c.items {
            if now.After(item.expiresAt) {
                delete(c.items, key)
            }
        }
        c.mu.Unlock()
    }
}

Business Hours Checker

go
type BusinessHours struct {
    timezone     *time.Location
    openTime     time.Duration  // Duration since midnight
    closeTime    time.Duration  // Duration since midnight
    workdays     []time.Weekday
    holidays     []time.Time
}

func NewBusinessHours(timezone string) (*BusinessHours, error) {
    loc, err := time.LoadLocation(timezone)
    if err != nil {
        return nil, err
    }

    return &BusinessHours{
        timezone:  loc,
        openTime:  9 * time.Hour,  // 9 AM
        closeTime: 17 * time.Hour, // 5 PM
        workdays: []time.Weekday{
            time.Monday, time.Tuesday, time.Wednesday,
            time.Thursday, time.Friday,
        },
        holidays: []time.Time{},
    }, nil
}

func (bh *BusinessHours) IsBusinessTime(t time.Time) bool {
    // Convert to business timezone
    localTime := t.In(bh.timezone)

    // Check if it's a workday
    isWorkday := false
    for _, day := range bh.workdays {
        if localTime.Weekday() == day {
            isWorkday = true
            break
        }
    }

    if !isWorkday {
        return false
    }

    // Check if it's a holiday
    for _, holiday := range bh.holidays {
        if isSameDate(localTime, holiday.In(bh.timezone)) {
            return false
        }
    }

    // Check business hours
    todayStart := time.Date(localTime.Year(), localTime.Month(), localTime.Day(),
        0, 0, 0, 0, bh.timezone)

    openTime := todayStart.Add(bh.openTime)
    closeTime := todayStart.Add(bh.closeTime)

    return localTime.After(openTime) && localTime.Before(closeTime)
}

func isSameDate(t1, t2 time.Time) bool {
    y1, m1, d1 := t1.Date()
    y2, m2, d2 := t2.Date()
    return y1 == y2 && m1 == m2 && d1 == d2
}

Performance Measurement

go
type PerformanceTracker struct {
    measurements map[string][]time.Duration
    mu          sync.Mutex
}

func NewPerformanceTracker() *PerformanceTracker {
    return &PerformanceTracker{
        measurements: make(map[string][]time.Duration),
    }
}

func (pt *PerformanceTracker) Track(name string, fn func()) {
    start := time.Now()
    fn()
    elapsed := time.Since(start)

    pt.mu.Lock()
    pt.measurements[name] = append(pt.measurements[name], elapsed)
    pt.mu.Unlock()
}

func (pt *PerformanceTracker) Stats(name string) (avg, min, max time.Duration, count int) {
    pt.mu.Lock()
    durations := pt.measurements[name]
    pt.mu.Unlock()

    if len(durations) == 0 {
        return 0, 0, 0, 0
    }

    var total time.Duration
    min = durations[0]
    max = durations[0]

    for _, d := range durations {
        total += d
        if d < min {
            min = d
        }
        if d > max {
            max = d
        }
    }

    avg = total / time.Duration(len(durations))
    count = len(durations)
    return
}

Conclusion

This comprehensive guide covers all essential aspects of Go's time package, from basic usage to advanced patterns and best practices. The examples demonstrate real-world applications and help avoid common pitfalls when working with time in Go applications.

>>> Follow and Contact Relia Software for more information!

  • golang
  • coding