Вычитание time.Duration из time.Time в Go: как правильно?
Используйте метод Add() с отрицательным значением
В Go для вычитания интервала из time.Time используется метод Add(), который принимает time.Duration. Чтобы вычесть время, передайте отрицательное значение длительности. Это самый простой и идиоматичный способ.
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
// Вычитаем 24 часа: передаём -24 * time.Hour
yesterday := now.Add(-24 * time.Hour)
fmt.Println("Сейчас:", now)
fmt.Println("Вчера:", yesterday)
}
Также можно использовать time.Duration с отрицательным знаком:
duration := 24 * time.Hour
yesterday := now.Add(-duration) // эквивалентно now.Add(-24 * time.Hour)
Почему это работает?
Метод Add() определён для time.Time и возвращает новое значение, смещённое на указанную длительность. Отрицательная длительность — это просто способ сказать "назад во времени". Никаких операторов вроде - для структур не нужно, Go использует методы для таких операций.
Дополнительные примеры
- Вычитание нескольких часов:
twoHoursAgo := now.Add(-2 * time.Hour) - Вычитание минут и секунд:
tenMinutesAgo := now.Add(-10 * time.Minute) - Комбинирование длительностей:
complexDuration := 2*time.Hour + 30*time.Minute + 15*time.Second
result := now.Add(-complexDuration) - Вычитание с учётом локали:
now.In(time.UTC).Add(-24 * time.Hour)
Важные замечания
Не путайте метод Sub() — он предназначен для вычисления разницы между двумя time.Time и возвращает time.Duration. Для вычитания интервала используйте только Add() с отрицательным значением.
// Правильно: вычитание интервала
past := now.Add(-24 * time.Hour)
// Неправильно: Sub() для другой цели
diff := now.Sub(past) // diff == 24 * time.Hour
Также помните, что при работе с переходами на летнее/зимнее время Add() учитывает календарные изменения. Если вам нужно именно "вчера в то же календарное время", используйте AddDate(0, 0, -1), но это может дать другой результат из-за сдвига часов.
Альтернативный подход: использование AddDate()
Если вам нужно вычесть не просто интервал времени, а календарный день, месяц или год, удобнее использовать метод AddDate(). Он принимает три аргумента: годы, месяцы, дни (могут быть отрицательными).
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
// Вычитаем 1 день (календарно)
yesterday := now.AddDate(0, 0, -1)
fmt.Println("Вчера (календарно):", yesterday)
// Вычитаем 1 месяц
lastMonth := now.AddDate(0, -1, 0)
fmt.Println("Месяц назад:", lastMonth)
}
Этот метод полезен, когда важна календарная дата, а не точное количество часов. Например, если сейчас 15 марта 14:00, то AddDate(0,0,-1) вернёт 14 марта 14:00, даже если 14 марта был переход на летнее время (в этом случае разница может быть 23 или 25 часов). Add(-24*time.Hour) всегда отнимет ровно 24 часа, что может привести к другому времени суток.
Выбирайте подход в зависимости от задачи: для точных интервалов — Add() с отрицательной длительностью, для календарных операций — AddDate().
Ответов пока нет.
Войдите чтобы оставить ответ