golang gin框架進行時間運算之解決orm時間與時間運算——附原始碼

wangchunbo發表於2021-04-20

問題: 進行資料庫時間對比。欄位有datetime型別,有int型別(表示分鐘)。需要判斷是否超時

越轉出現問題越多。

索性直接使用函式。

分析:

time 結構體為

type Time struct {
    wall unit64     //表示距離公元1年1月1日00:00:00UTC的秒數
    ext  int64      //表示納秒
    loc  *Location  //代表時區,主要處理偏移量。因為不同的時區,對應的時間不一樣
}

那我查詢出來的mysql欄位,有datetime型別,有int
所以這裡,最好的方法其實不是像php那樣進行轉換,timestamp

而是直接使用 time 函式

time 函式解決方案演示

程式碼部分截圖

m, _ := time.ParseDuration(fmt.Sprintf("%dm", testInfo.CurrentLimitMaxTime))
now := time.Now()

// 如果 當前時間 >= 相加的時間   超時
if now.Sub(time.Time(testInfo.PickTime).Add(m)) >= 0 {

}

time 函式的使用

官方文件函式列表: docscn.studygolang.com/pkg/time/

可以自行檢視使用哈。
golang 進行時間運算,儘量使用time函式的方法,別轉來轉去。

orm time 的封裝

參考文件程式碼連結: www.cnblogs.com/Chaser-Eagle/p/131...

ormtime.go


package util

import (
    "database/sql/driver"
    "encoding/json"
    "fmt"
    "time"
)

const timeFormat = "2006-01-02 15:04:05"

type MyTime time.Time

func (this *MyTime) UnmarshalJSON(data []byte) (err error) {
    now, err := time.ParseInLocation(`"`+timeFormat+`"`, string(data), time.Local)
    *this = MyTime(now)
    return
}

func (this MyTime) MarshalJSON() ([]byte, error) {
    tt := time.Time(this)
    if tt.IsZero() {
        emptyStr, _ := json.Marshal("")
        return emptyStr, nil
    }
    b := make([]byte, 0, len(timeFormat)+2)
    b = append(b, '"')
    b = tt.AppendFormat(b, timeFormat)
    b = append(b, '"')
    return b, nil
}

func (this MyTime) Value() (driver.Value, error) {
    var zeroTime time.Time
    tt := time.Time(this)
    if tt.UnixNano() == zeroTime.UnixNano() {
        return nil, nil
    }
    return tt, nil
}

func (this *MyTime) Scan(v interface{}) error {
    value, ok := v.(time.Time)
    if ok {
        *this = MyTime(value)
        return nil
    }
    return fmt.Errorf("can not convert %v to timestamp", v)
}

func (this MyTime) IsZero() bool {
    tt := time.Time(this)
    if tt.IsZero() {
        return true
    }
    return false
}

func (this MyTime) String() string {
    tt := time.Time(this)
    return tt.String()
}

func (this MyTime) Format() string {
    tt := time.Time(this)
    return tt.Format(timeFormat)
}

func (this MyTime) After(t MyTime) bool {
    tt := time.Time(this)
    return tt.After(time.Time(t))
}

func (this MyTime) Before(t MyTime) bool {
    tt := time.Time(this)
    return tt.Before(time.Time(t))
}

func (this MyTime) Parse(t string) (MyTime, error) {
    tt, err := time.Parse(timeFormat, t)
    return MyTime(tt), err
}

呼叫方法:在 orm宣告中:

`type TestDao struct{`

`Id    uint    `gorm:"primary_key,AUTO_INCREMENT" json:"id"``

`CreatedAt  MyTime `json:"-"``

`UpdatedAt  MyTime `json:"update_at"``

`DeletedAt  *MyTime `json:"-"``

`}`

實現原理

其實現方式其實是通過在save變更時,通過callback功能,將其定義為當前時間。文章可參考 傳送門

這樣你就可以通過自定義的LocalTime來控制時間格式。

弊端與建議

因為在程式執行時,createAt這類欄位的型別還是 LocalTime,所以如果你想自己給其複製,是不太容易做到的。

例如,你想在程式執行時改一下其createAt的時間。你做不到! 因為它的型別是LocalTime,而你的時間要麼是時間戳,要麼是一個字串,型別不匹配。。。是不是很尷尬???

所以建議這類保留欄位還是不要在程式執行時去修改。只用它作為記錄或標識即可。如果真的需要更改時間,還是自己維護欄位的內容吧。例如用int存時間戳或string存字串。然後每次變更時,去修改它的值。

當然也可以將這工作自己封裝成一個callback函式,這樣你就能夠隨意控制這個欄位了。可參考上文傳送門中的內容。

所以,想吐槽的是,go orm對時間格式化的這種實現方式,太不人性化了!

本作品採用《CC 協議》,轉載必須註明作者和本文連結
感謝關注 上海PHP自學中心-免費程式設計視訊教學|

相關文章