# Time and Date

Course: [Go](https://www.devtutorials.ai/learn/go) · Section: Strings and Time
Source: https://www.devtutorials.ai/learn/go/strings-and-time/time-and-date

> Work with time.Time and time.Duration: get the current time, build and parse dates, read their parts, add, subtract and compare times, and format them with Go's reference layout.

## What Is the time Package?

**time package** = Go's standard package for dates, times and lengths of time.

With it, a program can:

- read the current date and time
- make a date, like the day of the annual exam
- add days, or find how long until an event
- print a date in any style, like `14/03/2025`

**Simple lesson:** the `time` package handles every date, clock time and length of time.

### A Real-World Example

The school timetable office works with time all day.

- The exam **starts** on 14 March 2025 at 9:30 AM.
- Each paper **lasts** 3 hours.
- Results come out **30 days** after the last exam.
- The notice board shows dates as `14/03/2025`.

In Go:

- A moment, like "14 March 2025, 9:30 AM", is a `time.Time`.
- A length of time, like "3 hours", is a `time.Duration`.
- The notice board style is a **layout** for `Format`.

Cells that use the **current** time print something different on every run.

Those cells are marked so the course checker does not compare their output. Fixed dates print the same every time.

## What You Will Learn

In this lesson, you will learn:

1. What a `time.Time` is, and how to get the current time.
2. How to make dates with `time.Now()`, `time.Date()` and `time.Parse()`.
3. How to read the parts of a time: year, month, day, hour, minute, second.
4. How to add, subtract and compare times.
5. How `time.Duration` stores lengths of time.
6. How to format and parse times with Go's layout.

## Time Package Fundamentals

### time.Time

**time.Time** = one exact moment: a date, a clock time, and a time zone.

- It is a value, like an `int` or a `string`.
- Its zero value is 1 January of year 1, at midnight UTC.
- `t.IsZero()` tells you if a time was never set.

**UTC** = the world's standard clock time. India Standard Time (IST) is UTC + 5:30.

### Current Time

```go runnable varies title="The time right now"
package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println(now)
	fmt.Println("Year:", now.Year())
}
```

- `time.Now()` gives the current moment.
- The output changes every time you run it.
- In this lab, the time zone may show as UTC. On your computer it shows your local zone.

**Simple lesson:** a `time.Time` is one moment, and `time.Now()` gives the moment right now.

## Date Creation

There are three common ways to get a `time.Time`.

### time.Date()

```go runnable title="Make the exam date"
package main

import (
	"fmt"
	"time"
)

func main() {
	exam := time.Date(2025, time.March, 14, 9, 30, 0, 0, time.UTC)
	fmt.Println(exam)
}
```

```text
2025-03-14 09:30:00 +0000 UTC
```

- Months are written as `time.March`, or as the number `3` turned into `time.Month(3)`.
- The hour uses the 24-hour clock: `14` is 2 PM.
- The last part is the time zone. `time.UTC` is the world standard.

### time.Parse()

**Parse** = read a value out of text.

```go runnable title="Read a date from text"
package main

import (
	"fmt"
	"time"
)

func main() {
	day, err := time.Parse("2006-01-02", "2025-12-25")
	fmt.Println(day, err)

	_, err = time.Parse("2006-01-02", "25-12-2025")
	fmt.Println(err)
}
```

```text
2025-12-25 00:00:00 +0000 UTC <nil>
parsing time "25-12-2025" as "2006-01-02": cannot parse "25-12-2025" as "2006"
```

- The first argument is the **layout**. It shows the shape of the text.
- When the text does not match, `err` explains why.
- You will learn layouts in **Formatting Time**.

### Time Zones

```go runnable title="The same moment in India"
package main

import (
	"fmt"
	"time"
)

func main() {
	exam := time.Date(2025, time.March, 14, 4, 0, 0, 0, time.UTC)
	ist := time.FixedZone("IST", 5*60*60+30*60)
	fmt.Println(exam.In(ist))
}
```

```text
2025-03-14 09:30:00 +0530 IST
```

- `t.In(zone)` shows the same moment in another time zone.
- `time.FixedZone` makes a zone from its name and its offset in seconds.
- On your computer, `time.LoadLocation("Asia/Kolkata")` also works.

**Simple lesson:** build a time with `time.Date`, read one from text with `time.Parse`, or take the current one with `time.Now`.

## Time Components

You can read each part of a time with a method.

```go runnable title="Parts of a time"
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2025, time.March, 14, 9, 30, 15, 0, time.UTC)
	fmt.Println("Year:", t.Year())
	fmt.Println("Month:", t.Month(), int(t.Month()))
	fmt.Println("Day:", t.Day())
	fmt.Println("Hour:", t.Hour())
	fmt.Println("Minute:", t.Minute())
	fmt.Println("Second:", t.Second())
	fmt.Println("Weekday:", t.Weekday())
	fmt.Println("Day of year:", t.YearDay())
}
```

```text
Year: 2025
Month: March 3
Day: 14
Hour: 9
Minute: 30
Second: 15
Weekday: Friday
Day of year: 73
```

- `t.Month()` prints as a name. `int(t.Month())` gives the number.
- `t.Weekday()` gives the day of the week.
- `t.YearDay()` counts days from 1 January: 31 + 28 + 14 = 73.

**Simple lesson:** methods like `Year()`, `Month()` and `Day()` read each part of a time.

## Duration

**time.Duration** = a length of time, like 3 hours or 45 minutes.

- Inside, it is a count of **nanoseconds** (billionths of a second).
- Go has ready-made units: `time.Hour`, `time.Minute`, `time.Second`, `time.Millisecond`.
- Multiply a unit to get a duration: `3 * time.Hour`.

### Hours, Minutes and Seconds

```go runnable title="Durations"
package main

import (
	"fmt"
	"time"
)

func main() {
	paper := 3 * time.Hour
	period := 45 * time.Minute
	day := 6*period + 30*time.Minute
	fmt.Println(paper, period, day)
	fmt.Println(day.Hours(), day.Minutes())
}
```

```text
3h0m0s 45m0s 5h0m0s
5 300
```

- A duration prints like `3h0m0s`: hours, minutes, seconds.
- `d.Hours()`, `d.Minutes()` and `d.Seconds()` give `float64` numbers.

### Reading a Duration from Text

```go runnable title="ParseDuration"
package main

import (
	"fmt"
	"time"
)

func main() {
	d, err := time.ParseDuration("1h45m")
	fmt.Println(d, err)
	fmt.Println(d.Minutes())
}
```

```text
1h45m0s <nil>
105
```

- Units in the text: `h`, `m`, `s`, `ms`.

A plain number is **nanoseconds**, not seconds.

`time.Duration(5)` is 5 nanoseconds. Write `5 * time.Second` for five seconds.

**Simple lesson:** a `time.Duration` is a length of time, made by multiplying units like `time.Hour`.

## Time Operations

Press **Play** to plan the exam week.

### Add and Sub

- `t.Add(d)` = the time `d` later. Use a negative `d` for earlier.
- `t.AddDate(years, months, days)` = move by calendar parts.
- `t2.Sub(t1)` = the `Duration` from `t1` to `t2`.

```go runnable title="Days until the annual day"
package main

import (
	"fmt"
	"time"
)

func main() {
	today := time.Date(2025, time.November, 1, 0, 0, 0, 0, time.UTC)
	annualDay := time.Date(2025, time.December, 20, 0, 0, 0, 0, time.UTC)
	left := annualDay.Sub(today)
	fmt.Println(left)
	fmt.Println("Days left:", int(left.Hours()/24))
}
```

```text
1176h0m0s
Days left: 49
```

### Before, After and Equal

```go runnable title="Compare two times"
package main

import (
	"fmt"
	"time"
)

func main() {
	deadline := time.Date(2025, time.June, 30, 17, 0, 0, 0, time.UTC)
	submitted := time.Date(2025, time.June, 30, 16, 45, 0, 0, time.UTC)
	fmt.Println(submitted.Before(deadline))
	fmt.Println(submitted.After(deadline))
	fmt.Println(deadline.Equal(deadline.Add(0)))
}
```

```text
true
false
true
```

- `Before`, `After` and `Equal` all give a `bool`.
- Use `Equal`, not `==`, to compare times. Two equal moments in different zones are `Equal`, but not `==`.

**Easy way to remember**

- `Time + Duration = Time` → `t.Add(d)`
- `Time - Time = Duration` → `t2.Sub(t1)`
- Calendar steps → `t.AddDate(0, 1, 0)` for one month

**Simple lesson:** `Add` moves a time, `Sub` measures the gap, and `Before`, `After`, `Equal` compare.

## Formatting Time

### Format()

**Format** = turn a `time.Time` into text, in the style you choose.

Go does not use codes like `YYYY` or `%d`.
It uses one **reference time** as the pattern:

```text
Mon Jan 2 15:04:05 MST 2006
```

- In order, it reads 1 2 3 4 5 6: month **1**, day **2**, hour **3** PM (15), minute **4**, second **5**, year **6** (2006).
- Write the reference time in the style you want. Go swaps in your time.

Pick a style, or type your own layout.

Try these:

- **`02/01/2006`:** the Indian style, day first.
- **`03:04 PM`:** a 12-hour clock.
- **`2006`** alone: only the year.

```go runnable title="Format one date in many styles"
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2025, time.March, 14, 9, 30, 0, 0, time.UTC)
	fmt.Println(t.Format("02/01/2006"))
	fmt.Println(t.Format("Monday, 2 January 2006"))
	fmt.Println(t.Format("03:04 PM"))
	fmt.Println(t.Format(time.RFC3339))
}
```

```text
14/03/2025
Friday, 14 March 2025
09:30 AM
2025-03-14T09:30:00Z
```

- `time.RFC3339` is a ready-made layout used by computers and APIs.

| Want | Write |
|---|---|
| year (4 digits) | `2006` |
| month (2 digits / name / short) | `01` / `January` / `Jan` |
| day (2 digits / no zero) | `02` / `2` |
| weekday (full / short) | `Monday` / `Mon` |
| hour 24h / 12h | `15` / `03` |
| minute, second | `04`, `05` |
| AM or PM | `PM` |

### Parse()

`time.Parse` uses the **same** layout idea, the other way round.

```go runnable title="Read an Indian-style date"
package main

import (
	"fmt"
	"time"
)

func main() {
	d, err := time.Parse("02/01/2006", "15/08/2025")
	if err != nil {
		fmt.Println("Bad date:", err)
		return
	}
	fmt.Println(d.Weekday(), d.Format("January 2, 2006"))
}
```

```text
Friday August 15, 2025
```

- The layout `02/01/2006` says: day, then month, then year.
- Always check `err`: typed dates are often wrong.

A layout with wrong numbers gives wrong output, with no error.

`t.Format("2025-03-14")` is not a layout. Go reads `2` as "day" and `5` as "second". Always write the reference date: `2006-01-02`.

**Simple lesson:** to format or parse, write the reference time `Mon Jan 2 15:04:05 2006` in the style you want.

## TL;DR

1. **time.Time** = one moment. **time.Duration** = a length of time.
2. **Make a time** = `time.Now()`, `time.Date(y, m, d, h, min, s, ns, zone)`, `time.Parse(layout, text)`.
3. **Parts** = `Year()`, `Month()`, `Day()`, `Hour()`, `Minute()`, `Second()`, `Weekday()`.
4. **Operations** = `t.Add(d)`, `t.AddDate(y, m, d)`, `t2.Sub(t1)`, `Before`, `After`, `Equal`.
5. **Duration** = `3 * time.Hour`. Read with `Hours()`, `Minutes()`, `Seconds()`.
6. **Layout** = the reference time `Mon Jan 2 15:04:05 MST 2006`.
   - `Format(layout)` = time to text. `Parse(layout, text)` = text to time.

## Common mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| `t.Format("YYYY-MM-DD")` | Go uses YYYY codes | Go uses the reference date | Prints `YYYY-MM-DD` as plain text. |
| `t.Format("dd/mm/yyyy")` | Lowercase codes work | Write `02/01/2006` | Wrong output, no error. |
| `time.Sleep(5)` for five seconds | A number means seconds | A number means nanoseconds | It waits 5 nanoseconds. |
| `t1 == t2` to compare times | `==` is fine | Use `t1.Equal(t2)` | False for the same moment in other zones. |
| Ignoring the `Parse` error | Text is always a valid date | Check `err` | A zero time used by mistake. |
| `days := d.Hours() / 24` stored in an int | It is an int | `Hours()` is a `float64` | A type error. Convert with `int(...)`. |
| `t.Month() + 1` printed as a number | `Month()` is an int | It is a `time.Month` and prints a name | You see `April`, not `4`. Use `int(t.Month())`. |

## Check Yourself

## Exercises

## What to Remember

- `time.Time` is a moment. `time.Duration` is a length of time.
- Make times with `time.Now()`, `time.Date(...)` or `time.Parse(...)`.
- `Add` and `AddDate` move a time. `Sub` gives the gap. Compare with `Before`, `After`, `Equal`.
- Write durations as `45 * time.Minute`, never a bare number.
- Layouts use the reference time `Mon Jan 2 15:04:05 MST 2006`.

Next: **Arrays**. You will learn how to keep a fixed number of values together in one variable.
