qrz/vendor/xorm.io/xorm/convert/time.go

183 lines
5.3 KiB
Go
Raw Normal View History

2021-08-30 19:45:06 +02:00
// Copyright 2021 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package convert
import (
"database/sql"
"fmt"
"strconv"
"strings"
"time"
"xorm.io/xorm/internal/utils"
)
// String2Time converts a string to time with original location
2023-10-01 12:09:07 +02:00
// be aware for time strings (HH:mm:ss) returns zero year (LMT) for converted location
2021-08-30 19:45:06 +02:00
func String2Time(s string, originalLocation *time.Location, convertedLocation *time.Location) (*time.Time, error) {
if len(s) == 19 {
if s == utils.ZeroTime0 || s == utils.ZeroTime1 {
return &time.Time{}, nil
}
dt, err := time.ParseInLocation("2006-01-02 15:04:05", s, originalLocation)
if err != nil {
return nil, err
}
dt = dt.In(convertedLocation)
return &dt, nil
} else if len(s) == 20 && s[10] == 'T' && s[19] == 'Z' {
2023-10-01 12:09:07 +02:00
if strings.HasPrefix(s, "0000-00-00T00:00:00") || strings.HasPrefix(s, "0001-01-01T00:00:00") {
return &time.Time{}, nil
}
2021-08-30 19:45:06 +02:00
dt, err := time.ParseInLocation("2006-01-02T15:04:05", s[:19], originalLocation)
if err != nil {
return nil, err
}
dt = dt.In(convertedLocation)
return &dt, nil
} else if len(s) == 25 && s[10] == 'T' && s[19] == '+' && s[22] == ':' {
2023-10-01 12:09:07 +02:00
if strings.HasPrefix(s, "0000-00-00T00:00:00") || strings.HasPrefix(s, "0001-01-01T00:00:00") {
return &time.Time{}, nil
}
2021-08-30 19:45:06 +02:00
dt, err := time.Parse(time.RFC3339, s)
if err != nil {
return nil, err
}
dt = dt.In(convertedLocation)
return &dt, nil
2023-10-01 12:09:07 +02:00
} else if len(s) >= 21 && s[10] == 'T' && s[19] == '.' {
if strings.HasPrefix(s, "0000-00-00T00:00:00."+strings.Repeat("0", len(s)-20)) ||
strings.HasPrefix(s, "0001-01-01T00:00:00."+strings.Repeat("0", len(s)-20)) {
return &time.Time{}, nil
}
dt, err := time.Parse(time.RFC3339Nano, s)
if err != nil {
return nil, err
}
dt = dt.In(convertedLocation)
return &dt, nil
2021-08-30 19:45:06 +02:00
} else if len(s) >= 21 && s[19] == '.' {
2023-10-01 12:09:07 +02:00
if strings.HasPrefix(s, "0000-00-00T00:00:00."+strings.Repeat("0", len(s)-20)) ||
strings.HasPrefix(s, "0001-01-01T00:00:00."+strings.Repeat("0", len(s)-20)) {
return &time.Time{}, nil
}
layout := "2006-01-02 15:04:05." + strings.Repeat("0", len(s)-20)
2021-08-30 19:45:06 +02:00
dt, err := time.ParseInLocation(layout, s, originalLocation)
if err != nil {
return nil, err
}
dt = dt.In(convertedLocation)
return &dt, nil
2022-07-16 11:43:41 +02:00
} else if len(s) == 10 && s[4] == '-' {
if s == "0000-00-00" || s == "0001-01-01" {
return &time.Time{}, nil
}
dt, err := time.ParseInLocation("2006-01-02", s, originalLocation)
if err != nil {
return nil, err
}
dt = dt.In(convertedLocation)
return &dt, nil
2023-10-01 12:09:07 +02:00
} else if len(s) == 8 && s[2] == ':' && s[5] == ':' {
dt, err := time.ParseInLocation("15:04:05", s, originalLocation)
if err != nil {
return nil, err
}
currentDate := time.Now()
// add current date for correct time locations
dt = dt.AddDate(currentDate.Year(), int(currentDate.Month()), currentDate.Day())
dt = dt.In(convertedLocation)
// back to zero year
dt = dt.AddDate(-currentDate.Year(), int(-currentDate.Month()), -currentDate.Day())
return &dt, nil
2021-08-30 19:45:06 +02:00
} else {
i, err := strconv.ParseInt(s, 10, 64)
if err == nil {
2023-10-01 12:09:07 +02:00
if i == 0 {
return &time.Time{}, nil
}
2021-08-30 19:45:06 +02:00
tm := time.Unix(i, 0).In(convertedLocation)
return &tm, nil
}
}
return nil, fmt.Errorf("unsupported conversion from %s to time", s)
}
// AsTime converts interface as time
func AsTime(src interface{}, dbLoc *time.Location, uiLoc *time.Location) (*time.Time, error) {
switch t := src.(type) {
case string:
return String2Time(t, dbLoc, uiLoc)
case *sql.NullString:
if !t.Valid {
return nil, nil
}
return String2Time(t.String, dbLoc, uiLoc)
case []uint8:
if t == nil {
return nil, nil
}
return String2Time(string(t), dbLoc, uiLoc)
case *sql.NullTime:
if !t.Valid {
return nil, nil
}
2023-10-01 12:09:07 +02:00
if utils.IsTimeZero(t.Time) {
return &time.Time{}, nil
}
2021-08-30 19:45:06 +02:00
z, _ := t.Time.Zone()
if len(z) == 0 || t.Time.Year() == 0 || t.Time.Location().String() != dbLoc.String() {
tm := time.Date(t.Time.Year(), t.Time.Month(), t.Time.Day(), t.Time.Hour(),
t.Time.Minute(), t.Time.Second(), t.Time.Nanosecond(), dbLoc).In(uiLoc)
return &tm, nil
}
tm := t.Time.In(uiLoc)
return &tm, nil
case *time.Time:
2023-10-01 12:09:07 +02:00
if utils.IsTimeZero(*t) {
return &time.Time{}, nil
}
2021-08-30 19:45:06 +02:00
z, _ := t.Zone()
if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbLoc.String() {
tm := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
t.Minute(), t.Second(), t.Nanosecond(), dbLoc).In(uiLoc)
return &tm, nil
}
tm := t.In(uiLoc)
return &tm, nil
case time.Time:
2023-10-01 12:09:07 +02:00
if utils.IsTimeZero(t) {
return &time.Time{}, nil
}
2021-08-30 19:45:06 +02:00
z, _ := t.Zone()
if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbLoc.String() {
tm := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
t.Minute(), t.Second(), t.Nanosecond(), dbLoc).In(uiLoc)
return &tm, nil
}
tm := t.In(uiLoc)
return &tm, nil
case int:
2023-10-01 12:09:07 +02:00
if t == 0 {
return &time.Time{}, nil
}
2021-08-30 19:45:06 +02:00
tm := time.Unix(int64(t), 0).In(uiLoc)
return &tm, nil
case int64:
2023-10-01 12:09:07 +02:00
if t == 0 {
return &time.Time{}, nil
}
2021-08-30 19:45:06 +02:00
tm := time.Unix(t, 0).In(uiLoc)
return &tm, nil
case *sql.NullInt64:
2023-10-01 12:09:07 +02:00
if t.Int64 == 0 {
return &time.Time{}, nil
}
2021-08-30 19:45:06 +02:00
tm := time.Unix(t.Int64, 0).In(uiLoc)
return &tm, nil
}
return nil, fmt.Errorf("unsupported value %#v as time", src)
}