22

I'm new to Go and I was creating a little console script. You can check my code here:

package main

import (
    "bufio"
    "fmt"
    "os"
    "time"
)

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Println("Calculate")
    fmt.Print("Hours and minutes: ")
    start, _, _ := reader.ReadLine()
    begin, err := time.Parse("2016-12-25 00:00:00", "2016-12-25 "+string(start)+":00")
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(begin)
}

I've seen a related question but I couldn't understand why.

This is the error I'm getting after running my code:

parsing time "2016-12-25 22:40:00": month out of range
0001-01-01 00:00:00 +0000 UTC

Any ideas on what am I doing wrong?

Thanks

Community
  • 1
  • 1
rafaelmorais
  • 1,323
  • 2
  • 24
  • 49
  • 1
    How about the latest version of this question from a day ago? https://stackoverflow.com/questions/40388246/convert-string-to-time-and-parse-in-golang – JimB Nov 04 '16 at 14:57
  • So, it has to be that date specifically? :O – rafaelmorais Nov 04 '16 at 15:15
  • 1
    How else is the function supposed to know the difference in each field if there's no defined value? – JimB Nov 04 '16 at 15:27

2 Answers2

30

You're using the wrong reference time in the layout parameter of time.Parse which should be Jan 2, 2006 at 3:04pm (MST)

Change your begin line to the following and it will work:

begin, err := time.Parse("2006-01-02 15:04:05", "2016-12-25 "+string(start)+":00")

func Parse

nosequeldeebee
  • 935
  • 9
  • 14
  • 1
    Do you know why the layout needs to have this specific date? – rafaelmorais Nov 04 '16 at 15:15
  • 4
    It is inspired from Unix's epoch time https://en.wikipedia.org/wiki/Unix_time. It is Go's version. Go needs to have a set reference time for layout or else every programmer would just choose some arbitrary reference date. – nosequeldeebee Nov 04 '16 at 15:19
  • 6
    It's not anything like the epoch, and that point in time doesn't mean anything like the Unix epoch does, but it's just a mnemonic for the elements of time (month, day, etc.). Think of it as `01/02 03:04:05PM '06 -0700` (1-2-3-4-5-6-7), and as long as you remember that single sequence, you can write `1`, `01`, `Jan`, or `January` without having to remember`%m`, `%b`, or `%B` as in `strftime`. – musiphil Sep 07 '17 at 22:45
  • 4
    this should help: https://golang.org/src/time/format.go?s=25155:25201#L92 – kio Sep 02 '20 at 18:19
  • 1
    now I have to remember the format in which this sequence resides. This: "01/02 03:04:05PM '06 -0700". This is not helpful either. Is 01 month? or day? Is year seperated or adjacent to the day and month? There are a lot to remember :/ – Onur Demir Feb 20 '23 at 12:38
0

To avoid having to remember the special date, I usually wrap the logic in a function:

package main

import (
   "fmt"
   "time"
)

func parseDate(value string) (time.Time, error) {
   layout := time.RFC3339[:len(value)]
   return time.Parse(layout, value)
}

func main() {
   start := "15:04"
   d, e := parseDate("2016-12-25T" + start)
   if e != nil {
      panic(e)
   }
   fmt.Println(d)
}
Zombo
  • 1
  • 62
  • 391
  • 407