178

I have a time.Time value obtained from time.Now() and I want to get another time which is exactly 1 month ago.

I know subtracting is possible with time.Sub() (which wants another time.Time), but that will result in a time.Duration and I need it the other way around.

Carson
  • 6,105
  • 2
  • 37
  • 45
Martijn van Maasakkers
  • 2,647
  • 3
  • 16
  • 20

4 Answers4

210

In response to Thomas Browne's comment, because lnmx's answer only works for subtracting a date, here is a modification of his code that works for subtracting time from a time.Time type.

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()

    fmt.Println("now:", now)

    count := 10
    then := now.Add(time.Duration(-count) * time.Minute)
    // if we had fix number of units to subtract, we can use following line instead fo above 2 lines. It does type convertion automatically.
    // then := now.Add(-10 * time.Minute)
    fmt.Println("10 minutes ago:", then)
}

Produces:

now: 2009-11-10 23:00:00 +0000 UTC
10 minutes ago: 2009-11-10 22:50:00 +0000 UTC

Not to mention, you can also use time.Hour or time.Second instead of time.Minute as per your needs.

Playground: https://play.golang.org/p/DzzH4SA3izp

Zia Ul Rehman Mughal
  • 2,119
  • 24
  • 44
cchio
  • 2,227
  • 1
  • 13
  • 11
  • 6
    Don't user `ParseDuration` for static values! Just use `-10 * time.Minute`, that's what those constants are defined for. E.g. just `time.Now().Add(-10 * time.Minute)` is all you would need. – Dave C Mar 26 '15 at 03:10
  • 48
    Wow, the time API is so inconsistent. time.Add is to add a duration, while time.Sub is to substract a time. Glad I found this answer because I was looking at the Sub function and I would never have guessed it has a different signature from Add. – laurent Oct 22 '15 at 13:33
  • 8
    Also note that go implicitly converts `now.Add(-10 * time.Minute)` to `now.Add(time.Duration(-10) * time.Minute)` in case your getting an error when multiplying a duration by an int value... – notzippy Oct 27 '15 at 17:27
171

Try AddDate:

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()

    fmt.Println("now:", now)

    then := now.AddDate(0, -1, 0)

    fmt.Println("then:", then)
}

Produces:

now: 2009-11-10 23:00:00 +0000 UTC
then: 2009-10-10 23:00:00 +0000 UTC

Playground: http://play.golang.org/p/QChq02kisT

lnmx
  • 10,846
  • 3
  • 40
  • 36
  • 41
    what about subtracting a time? – Thomas Browne Feb 24 '15 at 20:54
  • 40
    Subtracting **a time** and subtracting **time** are different operations. To subtract **a time**, you would call time.Now().Sub(time.Time{}) to get the difference as a Duration. To subtract **an amount of time**, say 1 minute, you'd have to do time.Now().Add(**time.Minute * -1**). The lack of symmetry between Sub() and Add() is infuriating. – jcope Sep 03 '20 at 21:54
  • 2
    Diff() or such would have been a much more intuitive alternative for calculating duration than the current Add/Sub confusion... – Ward D.S. Nov 09 '20 at 10:32
75

You can negate a time.Duration:

then := now.Add(- dur)

You can even compare a time.Duration against 0:

if dur > 0 {
    dur = - dur
}

then := now.Add(dur)

You can see a working example at http://play.golang.org/p/ml7svlL4eW

docwhat
  • 11,435
  • 6
  • 55
  • 54
  • 2
    There's a catch though: `-1 * dur` will work, but `d := -1 ; dur = d * dur` will generate an error: "mismatched types int and time.Duration" – BlakBat Aug 31 '16 at 14:00
  • 7
    That is the right answer for the question's title and it should be marked as the answer. – selalerer Nov 05 '16 at 14:26
4

There's time.ParseDuration which will happily accept negative durations, as per manual. Otherwise put, there's no need to negate a duration where you can get an exact duration in the first place.

E.g. when you need to substract an hour and a half, you can do that like so:

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()

    fmt.Println("now:", now)

    duration, _ := time.ParseDuration("-1.5h")

    then := now.Add(duration)

    fmt.Println("then:", then)
}

https://play.golang.org/p/63p-T9uFcZo

sanmai
  • 29,083
  • 12
  • 64
  • 76