Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

carbon.Date changed after marshal/unmarshal #178

Closed
artemklevtsov opened this issue Aug 12, 2023 · 8 comments
Closed

carbon.Date changed after marshal/unmarshal #178

artemklevtsov opened this issue Aug 12, 2023 · 8 comments
Labels
Bug Report a reproducible bug or regression

Comments

@artemklevtsov
Copy link

artemklevtsov commented Aug 12, 2023

Hello,

I encountered an issue with the following code:

package main

import (
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"github.com/golang-module/carbon/v2"
)

const dateLayout = "2006-01-02"

type Date struct {
	Time time.Time
}

// UnmarshalJSON decodes JSON representation date
func (d *Date) UnmarshalJSON(b []byte) error {
	s := strings.Trim(string(b), `"`) // remove quotes
	if s == "null" {
		return nil
	}

	t, err := time.Parse(dateLayout, s)
	if err != nil {
		return err
	}

	*d = Date{t}

	return nil
}

// MarshalJSON encode to JSON.
func (d Date) MarshalJSON() ([]byte, error) {
	if d.Time.IsZero() {
		return nil, nil
	}

	return []byte(fmt.Sprintf(`"%s"`, d.Time.Format(dateLayout))), nil
}

type A struct {
	Date1 carbon.Date `json:"date1"`
	Date2 Date        `json:"date2"`
}

func main() {
	a := A{
		Date1: carbon.Date{Carbon: carbon.CreateFromDate(2000, 1, 1, carbon.UTC)},
		Date2: Date{Time: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)},
	}

	data, err := json.Marshal(a)
	if err != nil {
		panic(err)
	}

	var b A

	err = json.Unmarshal(data, &b)
	if err != nil {
		panic(err)
	}

	fmt.Println(a.Date1.Carbon2Time().Unix(), b.Date1.Carbon2Time().Unix())
	fmt.Println(a.Date2.Time.Unix(), b.Date2.Time.Unix())
}

golang version: 1.21.0

carbon version: v2.2.3

time zone: Asia/Novokuznetsk

I expected to get:

946684800 946684800
946684800 946684800

But I actually get:

946715384 946659600
946684800 946684800

Thanks!

@artemklevtsov artemklevtsov added the Bug Report a reproducible bug or regression label Aug 12, 2023
@artemklevtsov
Copy link
Author

artemklevtsov commented Aug 12, 2023

More compact example:

package main

import (
	"fmt"

	"github.com/golang-module/carbon/v2"
)

func main() {
	d1 := carbon.Date{Carbon: carbon.CreateFromDateTime(2000, 1, 1, 0, 0, 0, carbon.UTC)}
	d2 := carbon.Date{Carbon: carbon.ParseByLayout(d1.ToDateString(), carbon.DateLayout, carbon.UTC)}
	fmt.Println(d1 == d2)
}

Output:

false

@gouguoyin
Copy link
Collaborator

gouguoyin commented Aug 28, 2023

Date1: carbon.Date{Carbon: carbon.CreateFromDate(2000, 1, 1, carbon.UTC)}

The hours, minutes, seconds and nanosecond of CreateFromDate come from now, you can view the source code

func (c Carbon) CreateFromDate(year, month, day int, timezone ...string) Carbon {
	now := c.Now(timezone...)
	hour, minute, second := now.Time()
	return c.create(year, month, day, hour, minute, second, now.Nanosecond(), timezone...)
}

@artemklevtsov
Copy link
Author

artemklevtsov commented Aug 29, 2023

Thank you. I understand why this is happening. But I think it should be equal:

fmt.Println(a.Date1.Carbon2Time().Unix(), b.Date1.Carbon2Time().Unix())
fmt.Println(a.Date2.Time.Unix(), b.Date2.Time.Unix())

@gouguoyin
Copy link
Collaborator

gouguoyin commented Sep 6, 2023

a := A{
    Date1: carbon.Date{Carbon: carbon.CreateFromDate(2000, 1, 1, carbon.UTC)},
    Date2: Date{Time: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)},
}

The timestamps of Date1 and Date2 are not equal,If you want equality, you can

Date1: carbon.Date{Carbon: carbon.CreateFromDate(2000, 1, 1, carbon.UTC).StartOfDay()},

or

Date1: carbon.Date{Carbon: carbon.CreateFromDateTimeNano(2000, 1, 1, 0, 0, 0, 0, carbon.UTC)},

@gouguoyin
Copy link
Collaborator

gouguoyin commented Sep 6, 2023

Fixed bugs in v2.2.6 where the time zone was lost after json.Unmarshal
v2.2.5
image
v2.2.6
image

@artemklevtsov
Copy link
Author

But code from the first post returns:

❯ go run main.go 
946743050 946684800
946684800 946684800
❯ cat go.mod 
module demo

go 1.21.0

require github.com/golang-module/carbon/v2 v2.2.6

@artemklevtsov
Copy link
Author

artemklevtsov commented Sep 6, 2023

I think it should be fixed: https://github.com/golang-module/carbon/issues/178#issuecomment-1695140491
Why are minutes and seconds used for the dates? Or we can add the separate method for this.

@gouguoyin
Copy link
Collaborator

gouguoyin commented Sep 6, 2023

image

In order to be consistent with the CreateFromTime method,if the year, month and day in CreateFromTime method are given as a default of 0, it is an illegal time format, so the default is taken from the current time.

@dromara dromara deleted a comment from artemklevtsov Sep 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Report a reproducible bug or regression
Projects
None yet
Development

No branches or pull requests

2 participants