It's not clear to me from the documentation how I would parse a date in this somewhat strange format. It seems like it might not be possible.
2016-07-08T08:34:24+00:00
The following does not work (go play link)
package main
import (
"fmt"
"time"
)
func main() {
date := "2016-07-08T08:34:24+00:00"
d, err := time.Parse("2006-01-02T15:04:05+07:00", date)
if err == nil {
fmt.Println(d)
} else {
fmt.Println(err)
}
}
Obviously a regexp could first check for this format and transform the + to a -, but that implies the standard library cant parse this date.
Go's reference layout uses -7 hours as the timezone offset, but you used +7 hours:
package main
import (
"fmt"
"time"
)
func main() {
date := "2016-07-08T08:34:24+00:00"
d, err := time.Parse("2006-01-02T15:04:05-07:00", date)
if err == nil {
fmt.Println(d)
} else {
fmt.Println(err)
}
}
https://play.golang.org/p/FNzx57R2jy
Related
Go newcomer here.
I have a date string 2018-06-07T16:16:57Z and I want to convert it to something like this mm/dd/yyyy hh:mm.
This seems to be a frequently asked question, but I can't seem to find any previous questions that work for me.
I'm reading in a time field and trying to convert like this
time := row["Date & Time"]
fmt.Println(time)
t, _ := time.Parse("2006-01-02 15:04:05 -0700 UTC", time)
fmt.Println(t)
But I think the issue is that I don't have a correct format string. I've tried a few resources to no success.
When I print t as is, I get 0001-01-01 00:00:00 +0000 UTC as a result, which is obviously incorrect.
What I'd like to do is convert the time I'm reading in like this
newTime := currentDate.Format("01/02/2006 hh:mm")
You have two issues.
First, you should not name the variable time as that is the name of a built-in package. I suppose you knew that and this is just a copy paste error.
Next, the string you pass to time.Parse() is a format string that should describe the format of the time string from your database. You already know what the format is: 2018-06-07T16:16:57Z, so just use that replacing the value with Go's reference time.
Here is working variant:
package main
import (
"fmt"
"time"
)
func main() {
tm := "2018-06-07T16:16:57Z"
fmt.Println(tm)
t, err := time.Parse("2006-01-02T15:04:05Z", tm)
if err != nil {
panic(err)
}
fmt.Println(t)
}
Run in playground
What's more the time format database uses is often described as RFC3339, which is also available as the time.RFC3339 constant in Go.
So using that simplifies your code even further:
package main
import (
"fmt"
"time"
)
func main() {
tm := "2018-06-07T16:16:57Z"
fmt.Println(tm)
t, err := time.Parse(time.RFC3339, tm)
if err != nil {
panic(err)
}
fmt.Println(t)
}
Run in playground
And if you prefer, you could also let the database driver convert the time for you by scanning it to a time.Time variable.
For example:
var tm time.Time
if err = row.Scan(&tm); err != nil {
panic(err)
}
fmt.Print(tm)
As #mkopriva describes the layout should be matched. Understand the layout which is 2006-01-02T15:04:05Z, go through Golang spec for layout use to convert the string to date
Parse parses a formatted string and returns the time value it
represents. The layout defines the format by showing how the reference
time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
and then use returned time value to Format the date according to your requirement.
package main
import (
"fmt"
"time"
)
func main() {
layout1 := "2006-01-02T15:04:05Z"
t, err := time.Parse(layout1, "2018-06-07T16:16:57Z")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(t.Format("01/02/2006 15:04"))
}
Check it on Go Playground
I'm sorry if this is a trivial question. This is currently what I have.
snapshot = "2017-07-25"
snapshotFilter := " AND cdate = %s"
snapshot, err := time.Parse(time.RFC3339, snapshot)
if err != nil {
log.Fatal(err)
}
queryFilter = queryFilter + fmt.Sprintf(snapshotFilter, pq.FormatTimestamp(snapshot))
This is the output
2017/09/12 09:59:34 parsing time "2017-07-25" as "2006-01-02T15:04:05Z07:": cannot parse "" as "T".
I'm trying to get snapshot in the correct format to insert it into a postgres query.
I'm using the
"database/sql"
"time"
"github.com/gorilla/mux"
"github.com/lib/pq"
EDIT: is seemed that this was more of an issue with postgres and the 2017-07-25 just needed to be in quotes and put inside the postgres query string.
As already suggested, use this:
package main
import (
"fmt"
"log"
"time"
)
const layout = "2006-01-02"
func main() {
snapshot := "2017-07-25"
t, err := time.Parse(layout, snapshot)
if err != nil {
log.Fatal(err)
}
fmt.Println(t)
}
As you can see in the documentation of constants for the time package there is a reference date
Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
which is used to specify date/time strings layout. So you provide a string and every occurrence of 3 gets replaced by the hour in 12h am/pm notation of your point in time and every occurrence of 15 gets replaced by the hour in 24h representation for example.
All the wrinkles and problems of such an approach are explained in some sample code in the documentation.
Many codes taken from Martini example, but this using Echo framework.
I can make it works in Martini but not in Echo.
server.go:
package main
import (
"database/sql"
"github.com/labstack/echo"
_ "github.com/lib/pq"
"html/template"
"io"
"log"
"net/http"
)
type Book struct {
Title, Author, Description string
}
type (
Template struct {
templates *template.Template
}
)
func (t *Template) Render(w io.Writer, name string, data interface{}) error {
return t.templates.ExecuteTemplate(w, name, data)
}
func main() {
e := echo.New()
db, err := sql.Open("postgres", "user=postgres password=apassword dbname=lesson4 sslmode=disable")
if err != nil {
log.Fatal(err)
}
t := &Template{
templates: template.Must(template.ParseFiles("public/views/testhere.html")),
}
e.Renderer(t)
e.Get("/post/:idnumber", func(c *echo.Context) {
rows, err := db.Query("SELECT title, author, description FROM books WHERE id=$1", c.Param("idnumber"))
if err != nil {
log.Fatal(err)
}
books := []Book{}
for rows.Next() {
b := Book{}
err := rows.Scan(&b.Title, &b.Author, &b.Description)
if err != nil {
log.Fatal(err)
}
books = append(books, b)
}
c.Render(http.StatusOK, "onlytestingtpl", books)
})
e.Run(":4444")
}
public/views/testhere.html:
{{define "onlytestingtpl"}}Book title is {{.Title}}. Written by {{.Author}}. The book is about {{.Description}}.{{end}}
I cannot figure out since no error message, and no SQL documentation of this framework. When running, it gives:
Book title is
(The variable not output value)
As I mentioned in a comment, you shouldn't execute a template that takes a struct with a slice of structs. Either use {{range}} in your template, or do
c.Render(http.StatusOK, "onlytestingtpl", books[0])
I'm trying to write a password generator. It requires that characters be in ASCII representation, but I'm trying to use crypto/rand. This provides numbers in big.Int format, though, and I need to convert the relevant lower 8 bits to a form usable in a string. I've tried converting from big.Int to uint8 with no luck so far.
Is there a good and easy method to do this? I have seen answers involving using encoding/binary to convert from int64 to [8]uint8, but those seem needlessly complex for my purpose. Any guidance at all would be appreciated :).
package main
import (
"fmt"
"math/big"
)
func main() {
mpInt := big.NewInt(0x123456789abcdef0)
b := byte(mpInt.Int64())
fmt.Printf("%02x", b)
}
f0
In action: http://play.golang.org/p/92PbLdiVsP
EDIT: Evan Shaw correctly points out in a comment bellow that the above code is actually incorrect for big Ints outside of int64 limits. Instead of pulling it from big.Bytes (which makes a copy of all of the bits representing a big.Int IIRC) it's probably more performant to use big.And:
package main
import (
"fmt"
"log"
"math/big"
)
func lsB(n *big.Int) byte {
var m big.Int
return byte(m.And(m.SetInt64(255), n).Int64())
}
func main() {
var mpInt big.Int
if _, ok := mpInt.SetString("0x123456789abcdef012342", 0); !ok {
log.Fatal()
}
fmt.Printf("%02x", lsB(&mpInt))
}
Playground: http://play.golang.org/p/pgkGEFgb8-
If you want to get bytes out of crypto/rand, I'd skip the use of big.Int and rand.Int() entirely and use either rand.Read() or rand.Reader:
package main
import (
"crypto/rand"
"fmt"
"io"
)
// If you want just a byte at a time ...
// (you could change 'byte' to int8 if you prefer)
func secureRandomByte() byte {
data := make([]byte, 1)
if _, err := rand.Read(data); err != nil {
// handle error
panic(err)
}
return data[0]
}
// If you want to read multiple bytes at a time ...
func genPassword(len int) (string, error) {
data := make([]byte, len)
if _, err := io.ReadFull(rand.Reader, data); err != nil {
// handle error
return "", err
}
for i := range data {
// XXX quick munge into something printable
data[i] &= 0x3F
data[i] += 0x20
}
return string(data), nil
}
func main() {
b := secureRandomByte()
fmt.Printf("%T = %v\n", b, b)
fmt.Println(genPassword(16))
}
Does anyone know of a way to read the metadata and or properties of a file using the go language?
package main
import (
"fmt"
"os"
)
func main() {
fi, err := os.Stat("filename")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(fi.Name(), fi.Size())
}
Use below code, please change your path at place "filename or entire path".
package main
import (
"fmt"
"os"
)
func main() {
//The file has to be opened first
f, err := os.Open("filename or entire path")
// The file descriptor (File*) has to be used to get metadata
fi, err := f.Stat()
// The file can be closed
f.Close()
if err != nil {
fmt.Println(err)
return
}
// fi is a fileInfo interface returned by Stat
fmt.Println(fi.Name(), fi.Size())
}