diff --git a/pkg/utils/datetimes.go b/pkg/utils/datetimes.go index 431ee356..521d62e9 100644 --- a/pkg/utils/datetimes.go +++ b/pkg/utils/datetimes.go @@ -2,7 +2,10 @@ package utils import ( "fmt" + "strings" "time" + + "github.com/mayswind/ezbookkeeping/pkg/errs" ) const ( @@ -74,6 +77,46 @@ func FormatTimezoneOffset(timezone *time.Location) string { return fmt.Sprintf("%s%02d:%02d", sign, hourAbsOffset, minuteAbsOffset) } +// ParseFromTimezoneOffset parses a formatted string in timezone offset format +func ParseFromTimezoneOffset(tzOffset string) (*time.Location, error) { + if len(tzOffset) != 6 { // +/-HH:MM + return nil, errs.ErrFormatInvalid + } + + sign := tzOffset[0] + + if sign != '-' && sign != '+' { + return nil, errs.ErrFormatInvalid + } + + offsets := strings.Split(tzOffset[1:], ":") + + if len(offsets) != 2 { + return nil, errs.ErrFormatInvalid + } + + hourAbsOffset, err := StringToInt32(offsets[0]) + + if err != nil { + return nil, err + } + + minuteAbsOffset, err := StringToInt32(offsets[1]) + + if err != nil { + return nil, err + } + + totalMinuteOffset := hourAbsOffset*60 + minuteAbsOffset + + if sign == '-' { + totalMinuteOffset = -totalMinuteOffset + } + + totalOffset := totalMinuteOffset * 60 + return time.FixedZone("Timezone", totalOffset), nil +} + // GetMinTransactionTimeFromUnixTime returns the minimum transaction time from unix time func GetMinTransactionTimeFromUnixTime(unixTime int64) int64 { return unixTime * 1000 diff --git a/pkg/utils/datetimes_test.go b/pkg/utils/datetimes_test.go index 4ec1f214..8971acbd 100644 --- a/pkg/utils/datetimes_test.go +++ b/pkg/utils/datetimes_test.go @@ -75,6 +75,37 @@ func TestFormatTimezoneOffset(t *testing.T) { assert.Equal(t, expectedValue, actualValue) } +func TestParseFromTimezoneOffset(t *testing.T) { + expectedValue := time.FixedZone("Timezone", 120*60) + actualValue, err := ParseFromTimezoneOffset("+02:00") + assert.Equal(t, nil, err) + assert.Equal(t, expectedValue, actualValue) + + expectedValue = time.FixedZone("Timezone", 345*60) + actualValue, err = ParseFromTimezoneOffset("+05:45") + assert.Equal(t, nil, err) + assert.Equal(t, expectedValue, actualValue) + + expectedValue = time.FixedZone("Timezone", -720*60) + actualValue, err = ParseFromTimezoneOffset("-12:00") + assert.Equal(t, nil, err) + assert.Equal(t, expectedValue, actualValue) + + expectedValue = time.FixedZone("Timezone", 0) + actualValue, err = ParseFromTimezoneOffset("+00:00") + assert.Equal(t, nil, err) + assert.Equal(t, expectedValue, actualValue) + + actualValue, err = ParseFromTimezoneOffset("00:00") + assert.NotEqual(t, nil, err) + + actualValue, err = ParseFromTimezoneOffset("0") + assert.NotEqual(t, nil, err) + + actualValue, err = ParseFromTimezoneOffset("1000") + assert.NotEqual(t, nil, err) +} + func TestGetMinTransactionTimeFromUnixTime(t *testing.T) { expectedValue := int64(1617228083000) actualValue := GetMinTransactionTimeFromUnixTime(1617228083)