Go time.Parse() getting "month out of range" error - go

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

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

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)
}

Related

time.Parse offset parsing fails with "cannot parse <x>00 as -0700"

I wish to convert a string timestamp (for which no timezone was provided) to a time with timezone of UTC -08:00.
Code:
package main
import (
"fmt"
"log"
"time"
)
func main() {
layout := "1/02/2006 15:04:05 -700"
cellContent := "7/28/2021 22:45:34"
t, err := time.Parse(layout, fmt.Sprintf("%s %s", cellContent, "-800"))
if err == nil {
fmt.Println(t.String())
} else {
log.Fatal(err)
}
}
This fails with message:
parsing time "7/28/2021 22:45:34 -800" as "1/02/2006 15:04:05 -700":
cannot parse "800" as " -700"
I believe I have an error in my layout string, but haven't been able to identify it. What am I doing wrong?
Go Playground
See comment from #Adrian, who nailed it.
The layout timezone must have a leading zero. Thanks!

Go regExRepl-Script does not change the text file

my go script should add one newline before matching the regEx-Search-String ^(.+[,]+\n).
The Prototype i had tested before into the editor:
i want add newlines before this lines: \n$1.
This works if i try it into the Text-Editor.
If i try this (see line 24) with my script it is changing nothing and sends no error.
Any ideas what i do wrong?
Example
i like to use PCRE like it works in this Example https://regex101.com/r/sB9wW6/17
Same Example here:
Example source
Dear sir,
Thanks for your interest.
expected result
#### here is a newline ####
Dear sir,
Thanks for your interest.
result is (produced by the script below)
Dear sir,
Thanks for your interest.
go script:
// replace in files and store the new copy of it.
package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
"time"
)
func visit(path string, fi os.FileInfo, err error) error {
matched, err := filepath.Match("*.csv", fi.Name())
if err != nil {
panic(err)
return err
}
if matched {
read, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
newContents := string(read)
newContents = regExRepl(`^(.+[,]+\n)`, newContents, `\n\n\n$1`)
var re = regexp.MustCompile(`[\W]+`)
t_yymmdd := regexp.MustCompile(`[\W]+`).ReplaceAllString(time.Now().Format(time.RFC3339), `-`)[:10]
t_hhss := re.ReplaceAllString(time.Now().Format(time.RFC3339), `-`)[11:19]
t_yymmddhhss := t_yymmdd + "_" + t_hhss
fmt.Println(t_yymmddhhss)
filePath := fileNameWithoutExtension(path) + t_yymmddhhss + ".csv"
err = ioutil.WriteFile(filePath, []byte(newContents), 0)
if err != nil {
panic(err)
}
}
return nil
}
func regExRepl(regExPatt string, newContents string, regExRepl string) string {
return regexp.MustCompile(regExPatt).ReplaceAllString(newContents, regExRepl)
}
func main() {
err := filepath.Walk("./november2020messages.csv", visit) // <== read all files in current folder 20:12:06 22:44:42
if err != nil {
panic(err)
}
}
func fileNameWithoutExtension(fileName string) string {
return strings.TrimSuffix(fileName, filepath.Ext(fileName))
}
for interpretation \n as newline don't us
`\n`` use "\n"
may use ^(.+[,]+) instead ^(.+[,]+\n) and ad (?m) before for multi-line replacements
this suggestion you could test here: https://play.golang.org/p/25_0GJ93oCT
The following example illustrates the difference (in golang-playground here https://play.golang.org/p/FkPwElhx-Xu ):
// example from:
package main
import (
"fmt"
"regexp"
)
func main() {
newContents := `line 1,
line 2
line a,
line b`
newContents1 := regexp.MustCompile(`^(.+[,]+\n)`).ReplaceAllString(newContents, `\n$1`)
fmt.Println("hi\n" + newContents1)
newContents1 = regexp.MustCompile(`(?m)^(.+[,]+\n)`).ReplaceAllString(newContents, "\n$1")
fmt.Println("ho\n" + newContents1)
}
Result:
hi
\nline 1,
line 2
line a,
line b
ho
line 1,
line 2
line a,
line b

Incorrect time-conversion in Go

I am trying to convert the time string "2020-02-01T12:30:00+01:00" (from the google calendar API) to time.Time format in Go, for some reason it keeps giving me "2020-01-01 12:30:00 +0000 UTC" as output (which is first of January, instead of first of February). Any idea what I'm doing wrong?
Thanks in advance!
package main
import (
"fmt"
"time"
"log"
)
func main() {
input := "2020-02-01T12:30:00+01:00"
output, err := StrToTime(input)
if err != nil{
log.Fatal(err)
}
fmt.Println(output)
}
func StrToTime(strDateTime string) (time.Time, error) {
layout := "2006-01-02T15:04:05+01:00"
t, err := time.Parse(layout, strDateTime)
if err != nil {
return time.Time{}, fmt.Errorf("could not parse datetime: %v", err)
}
return t, nil
}
It happens because you've specified the time offset portion wrong, it should be -07:00 not +01:00.
As of now it treats 01 as month portion, the second time, and overwrites the originally correctly parsed 02 as 01 (but not from the time offset part of the input).

How to get hours difference between two dates

I'm working for first time on Go, in this case i have a string on UTC format, I would like to know, how can I get the difference in hours between my date and the time now.
This is my current string
v := "2014-05-03 20:57 UTC"
Use time.Parse and time.Since:
package main
import (
"fmt"
"time"
)
const (
// See http://golang.org/pkg/time/#Parse
timeFormat = "2006-01-02 15:04 MST"
)
func main() {
v := "2014-05-03 20:57 UTC"
then, err := time.Parse(timeFormat, v)
if err != nil {
fmt.Println(err)
return
}
duration := time.Since(then)
fmt.Println(duration.Hours())
}
Have a look at the time package.
package main
import "fmt"
import "time"
func main() {
a, err := time.Parse("2006-01-02 15:04 MST", "2014-05-03 20:57 UTC")
if err != nil {
// ...
return
}
delta := time.Now().Sub(a)
fmt.Println(delta.Hours())
}

Output Go time in RFC3339 like MySQL format

In Holland we mostly use YYYY-MM-DD HH:MM:SS. How can I format that in Go? Everything I insert (even according the standard) gives weird numbers.
This is my code (p.Created is a NanoSeconds int64 object):
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"time"
)
const createdFormat = "2010-01-01 20:01:00" //"Jan 2, 2006 at 3:04pm (MST)"
type Post struct {
Id int64
Created int64
Title string
Body string
}
func main() {
// Establish database connection
dsn := "root#tcp(127.0.0.1:3306)/testdb"
con, err := sql.Open("mysql", dsn)
if err != nil {
log.Println("Couldn't connect to databse:", err)
} else {
log.Println("DB Connection established")
}
defer con.Close()
// Try to get something
row := con.QueryRow("SELECT * FROM posts LIMIT 1")
p := new(Post)
err = row.Scan(&p.Id, &p.Created, &p.Title, &p.Body)
if err != nil {
log.Println("Failed to fetch Post")
}
fmt.Println(p)
fmt.Println(time.Unix(0, p.Created).Format(createdFormat))
}
I could just concat time.Unix(0, p.Created).Year() etc., but that's not very clean and is an annoyance for consistency.
There were two mistakes in the above. For the format you need to make the output of that special date/time, and the parameters to time.Unix are the other way round (playground)
const createdFormat = "2006-01-02 15:04:05" //"Jan 2, 2006 at 3:04pm (MST)"
fmt.Println(time.Unix(1391878657, 0).Format(createdFormat))
Using the current time is just as easy
timestamp := time.Now().Format("2006-01-02 15:04:05")
fmt.Println(timestamp)

Resources