There are many situations in which you might want to subtract a duration from an existing time value.
One example is when creating a “last x hours” filter. You will want to create a time value that is x hours before the current time.
To do such a subtraction we (somewhat confusingly) need to use the Add
method on the time.Time
type. This method allows you to add or subtract a time.Duration
from a time.Time
value if you supply a negative duration.
Sub
method. This method doesn't do what we want: It returns the difference between time.Time
values. It does not subtract a duration from a time value.
If we such a duration on a timeline, you can see how we “move backwards” to create a new time value:
Depending on your situation you will want to use a time.Duration
value of a different resolution.
In Go, a time.Duration
value has a resolution of 1 nanosecond. You can multiple it with the available “unit” constants to convert to seconds, hours and days. See the examples below.
Subtracting seconds
In the example below we create t2
by subtracting 2 seconds from t1
.
package main
import (
"fmt"
"time"
)
func main() {
t1 := time.Date(2024, 2, 8, 13, 37, 11, 0, time.UTC)
t2 := t1.Add(-2 * time.Second) // Note the negative two.
fmt.Println(t1.String())
fmt.Println(t2.String())
}
Subtracting hours
This works similarly for hours, if we want t2
to be 3 hours before t1
, we can do the following:
package main
import (
"fmt"
"time"
)
func main() {
t1 := time.Date(2024, 2, 8, 13, 37, 11, 0, time.UTC)
t2 := t1.Add(-3 * time.Hour)
fmt.Println(t1.String())
fmt.Println(t2.String())
}
Adding days
You won’t find a time.Day
constant in the time
package. Mainly because this is where “ambiguity sets in”. Due to timezones and daylight saving time, days will not always take exactly 24 hours. In such situations you might want to look at t.AddDate
.
However, if you are working in UTC (where every day does have 24 hours), you can use the following code.
package main
import (
"fmt"
"time"
)
func main() {
t1 := time.Date(2024, 2, 8, 13, 37, 11, 0, time.UTC)
t2 := t1.Add(-24*time.Hour)
fmt.Println(t1.String())
fmt.Println(t2.String())
}
Please note that this is still not entirely correct due to leap seconds. But the Go time
package does not support those to start with, so I’m skipping them here as well.
Positive duration
By providing a positive duration, you can add durations to time.Time
values.
Location
The time.Time
values created by the Add
method will always be in the same location as the original time value.
Monotonic clock
If the original time.Time
value is created via time.Now()
, it will often contain a monotonic element. Calling Add
on such
a value will create a new value that also contain a monotonic element. With the monotonic element adjusted for the duration provided to Add
.
This is the only way to create new time.Time
values that have monotonic elements without calling time.Now()
.
Get my free newsletter every second week
Used by 500+ developers to boost their Go skills.
"I'll share tips, interesting links and new content. You'll also get a brief guide to time for developers for free."