Reputation: 57451
I'm trying to define a Time
struct which implements the Marshaler
interface such that, when it is marshaled to JSON, it is represented in the format YYYY-mm-ddTHH:MM:SSZ
, that is, the time is converted to UTC and rounded to the nearest second. I've tried the following program:
package main
import (
"encoding/json"
"fmt"
"log"
"time"
)
type Time struct {
time.Time
}
func (t *Time) MarshalJSON() ([]byte, error) {
return []byte(t.Time.UTC().Round(time.Second).Format(time.RFC3339)), nil
}
func main() {
tm := time.Now()
// tm := time.Now().UTC().Round(time.Second)
tmJSON, err := json.Marshal(tm)
if err != nil {
log.Fatalf("marshal time: %v", err)
}
fmt.Println(string(tmJSON))
}
When I run this, however, it prints
> go run main.go
"2022-12-07T16:32:51.494597-08:00"
If, by contrast, I pass in time.Now().UTC().Round(time.Second)
as the input to be marshaled (i.e., use the commented-out line in the snippet above), I get the desired output:
> go run main.go
"2022-12-08T00:41:10Z"
My question is: why can't I perform the conversion to UTC and rounding to the nearest second in the MarshalJSON
method itself?
Upvotes: -2
Views: 2097
Reputation: 680
You can use AppendFormat
to convert your time string into buffer.
Also in your question you are not initialising your Time
struct for Marshalling.
Here is a probable solution
package main
import (
"encoding/json"
"errors"
"fmt"
"log"
"time"
)
type Time struct {
time.Time
}
func (t *Time) MarshalJSON() ([]byte, error) {
if y := t.Year(); y < 0 || y >= 10000 {
return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
}
b := make([]byte, 0, len(time.RFC3339)+2)
b = append(b, '"')
b = t.UTC().Round(time.Second).AppendFormat(b, time.RFC3339)
b = append(b, '"')
return b, nil
}
func main() {
now := time.Now()
mt := &Time{now}
bytArr, err := json.Marshal(mt)
if err != nil {
log.Fatalf("marshal time: %v", err)
}
fmt.Println(string(bytArr))
}
Upvotes: 0
Reputation: 169
what are you trying to do?
I tried running your MarshalJSON
function and it works as expected
here is what I tried to do:
package main
import (
"encoding/json"
"fmt"
"log"
"time"
)
type Time struct {
time.Time
}
func (t *Time) MarshalJSON() ([]byte, error) {
return []byte(t.Time.UTC().Round(time.Second).Format(time.RFC3339)), nil
}
func main() {
// tm := time.Now().UTC()
tm := time.Now().UTC().Round(time.Second)
tmJSON, err := json.Marshal(tm)
if err != nil {
log.Fatalf("marshal time: %v", err)
}
fmt.Println(string(tmJSON))
marshal_time := Time{time.Now().UTC()}
byt_arr, _ := marshal_time.MarshalJSON()
fmt.Println(string(byt_arr))
}
and i got the following output:
"2022-12-08T04:41:59Z"
2022-12-08T04:41:59Z
The first line is your previous output and the second output is of your MarshalJSON
function.
Upvotes: 2