当使用自定义类型时,日期的格式会发生变化。

huangapple go评论81阅读模式
英文:

Format of date changes when using it via custom types

问题

我对golang非常陌生,仍然在许多方面苦苦挣扎。

当实现自定义类型时,例如type Date time.Time,并定义一个方法来编组/解组以"2006-01-02"格式出现的日期(来自JSON文件和POST API请求),结构体中日期的最终存储方式是:

{wall:0 ext:63776764800 loc:<nil>}

有人可以帮助我理解为什么会出现这种格式(而不是常规的time.Time),因为自定义类型Date是大写的,因此是公开的吗?

这里是一个实现(代码下方有指向playground的链接):

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"time"
)

const sample = `{
    "ID": "1",
    "ticker": "S30J2",
    "issueDate": "2022-01-31",
    "maturity": "2023-06-30",
    "coupon": 0,
    "cashFlow": [
        {   "date": "2022-06-30",
            "rate": 0,
            "amortization": 1,
            "residual": 0,
            "amount": 50},
            {
            "date": "2023-06-30",
            "rate": 0,
            "amortization": 1,
            "residual": 0,
            "amount": 50}
    ]
}`

type Date time.Time

func (d Date) MarshalJSON() ([]byte, error) {
	return []byte(time.Time(d).Format("2006-1-2")), nil
}

func (d *Date) UnmarshalJSON(b []byte) error {
	// Disregard leading and trailing "
	t, err := time.Parse("2006-1-2", string(b[1:len(b)-2]))
	if err != nil {
		return err
	}
	*d = Date(t)
	return nil
}

type Flujo struct {
	Date     Date
	Rate     float64
	Amort    float64
	Residual float64
	Amount   float64
}
type Bond struct {
	ID        string
	Ticker    string
	IssueDate Date
	Maturity  Date
	Coupon    float64
	Cashflow  []Flujo
}

func main() {
	var b Bond
	if err := json.Unmarshal([]byte(sample), &b); err != nil {
		log.Fatalf("%s", err)
	}
	fmt.Printf("%+v\n", b.IssueDate)
	// I need to wrap it via Format.
	fmt.Println("Fecha: ", time.Time(b.IssueDate).Format("2006-01-02"))

}

这里是一个可工作的示例:https://go.dev/play/p/YddzXA9PQdP

感谢帮助和理解。

英文:

I'm very new to golang and still struggling with many things.

When implementing custom type like this type Date time.Time, an defining a method to marshal/unmarshal dates that come in &quot;2006-01-02&quot; format (from a JSON file and from a POST API request), the final way in which dates are stored in the struct is:

{wall:0 ext:63776764800 loc:&lt;nil&gt;}

Can someone help me understand why that format (instead of regular time.Time) since the custom type Date is capitalized, hence exported?

Here an implementation (link to playground below the code):

package main
import (
&quot;encoding/json&quot;
&quot;fmt&quot;
&quot;log&quot;
&quot;time&quot;
)
const sample = `{
&quot;ID&quot;: &quot;1&quot;,
&quot;ticker&quot;: &quot;S30J2&quot;,
&quot;issueDate&quot;: &quot;2022-01-31&quot;,
&quot;maturity&quot;: &quot;2023-06-30&quot;,
&quot;coupon&quot;: 0,
&quot;cashFlow&quot;: [
{   &quot;date&quot;: &quot;2022-06-30&quot;,
&quot;rate&quot;: 0,
&quot;amortization&quot;: 1,
&quot;residual&quot;: 0,
&quot;amount&quot;: 50},
{
&quot;date&quot;: &quot;2023-06-30&quot;,
&quot;rate&quot;: 0,
&quot;amortization&quot;: 1,
&quot;residual&quot;: 0,
&quot;amount&quot;: 50}
]
}`
type Date time.Time
func (d Date) MarshalJSON() ([]byte, error) {
return []byte(time.Time(d).Format(&quot;2006-1-2&quot;)), nil
}
func (d *Date) UnmarshalJSON(b []byte) error {
// Disregard leading and trailing &quot;
t, err := time.Parse(&quot;2006-1-2&quot;, string(b[1:len(b)-2]))
if err != nil {
return err
}
*d = Date(t)
return nil
}
type Flujo struct {
Date     Date
Rate     float64
Amort    float64
Residual float64
Amount   float64
}
type Bond struct {
ID        string
Ticker    string
IssueDate Date
Maturity  Date
Coupon    float64
Cashflow  []Flujo
}
func main() {
var b Bond
if err := json.Unmarshal([]byte(sample), &amp;b); err != nil {
log.Fatalf(&quot;%s&quot;, err)
}
fmt.Printf(&quot;%+v\n&quot;, b.IssueDate)
// I need to wrap it via Format.
fmt.Println(&quot;Fecha: &quot;, time.Time(b.IssueDate).Format(&quot;2006-01-02&quot;))
}

Here the working example: https://go.dev/play/p/YddzXA9PQdP

Thanks for the help and understanding.

答案1

得分: 2

类型Date是一个与time.Time不同的新命名类型,并且它没有为time.Time定义的方法。marshal/unmarshal方法可以正常工作,但是fmt.Print系列函数会使用Stringer接口(如果存在)。因此,如果你声明如下:

func (d Date) String() string {
	x, _ := d.MarshalJSON()
	return string(x)
}

它将正确打印输出。

英文:

The type Date is a new named type distinct from time.Time, and it does not have the methods defined for time.Time. The marshal/unmarshal methods work just fine, but fmt.Print family of function use the Stringer interface if one exists. Thus if you declare:

func (d Date) String() string {
x, _ := d.MarshalJSON()
return string(x)
}

It will print correctly.

huangapple
  • 本文由 发表于 2022年3月22日 00:25:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/71560863.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定