master v1.0.0
杨赟 2 years ago
commit 8e7a9e733d

12
.gitignore vendored

@ -0,0 +1,12 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 golangkit
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,45 @@
[![](https://img.shields.io/github/license/golangkit/formatime)](https://img.shields.io/github/license/golangkit/formatime)
[![GoDoc](https://godoc.org/github.com/golangkit/formatime?status.svg)](https://godoc.org/github.com/golangkit/formatime)
# formatime
自定义golang时间的格式能与gorm结合使用无需再使用sql.nullTime并能在struct的json序列化中返回指定的时间格式
## 安装
```bash
go get github.com/golangkit/formatime
```
## 使用
```go
type foo struct {
CreatedAt formatime.Date `gorm:"column:created_at" json:"created_at"`
UpdatedAt formatime.Timestamp `gorm:"column:updated_at" json:"updated_at"`
DeletedAt formatime.CustomTime `gorm:"column:deleted_at" json:"deleted_at"`
}
func Test_datetime(t *testing.T) {
b := foo{
CreatedAt: formatime.NewDateNow(),
UpdatedAt: formatime.NewTimestampNow(),
DeletedAt: formatime.NewCustomTimeNow("Jan _2 15:04:05"),
}
text, err := json.Marshal(&b)
if err != nil {
t.Fatal(err)
} else {
log.Print(string(text))
}
}
```
```javascript
// log结果如下
{
"created_at":"2019-10-29",
"updated_at":"1572312916",
"deleted_at":"Oct 29 09:35:16"
}
```

@ -0,0 +1,58 @@
[![](https://img.shields.io/github/license/golangkit/formatime)](https://img.shields.io/github/license/golangkit/formatime)
[![GoDoc](https://godoc.org/github.com/golangkit/formatime?status.svg)](https://godoc.org/github.com/golangkit/formatime)
# formatime
[中文](./README.cn.md)
Customize the format of the time in golang, can be used in conjunction with the gorm, no need to use sql.nullTime, and can return the specified time format in the json serialization of the struct
## Installation
```bash
go get github.com/golangkit/formatime
```
## Usage
```go
type foo struct {
ID int64 `gorm:"column:id"`
CreatedAt formatime.Date `gorm:"column:created_at" json:"created_at"`
UpdatedAt formatime.Timestamp `gorm:"column:updated_at" json:"updated_at"`
DeletedAt formatime.CustomTime `gorm:"column:deleted_at" json:"deleted_at"`
}
func Test_json(t *testing.T) {
b := foo{
CreatedAt: formatime.NewDateNow(),
UpdatedAt: formatime.NewTimestampNow(),
DeletedAt: formatime.NewCustomTimeNow("Jan _2 15:04:05"),
}
text, err := json.Marshal(&b)
if err != nil {
t.Fatal(err)
} else {
log.Print(string(text))
}
}
func Test_gorm(t *testing.T) {
b := &foo{}
gorm.DB.First(b)
text, err := json.Marshal(&b)
if err != nil {
t.Fatal(err)
} else {
log.Print(string(text))
}
}
```
```javascript
// log
{
"created_at":"2019-10-29",
"updated_at":"1572312916",
"deleted_at":"Oct 29 09:35:16"
}
```

@ -0,0 +1,73 @@
package formatime
import (
"fmt"
"time"
)
// CustomTime is a nullable time.Time. It supports SQL, JSON serialization AND custom format.
// It will marshal to null if null.
type CustomTime struct {
protocol
Format string
}
// new custom format of time, s is timestamp
// examples:
// ANSIC = "Mon Jan _2 15:04:05 2006"
// UnixDate = "Mon Jan _2 15:04:05 MST 2006"
// RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
// RFC822 = "02 Jan 06 15:04 MST"
// RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
// RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
// RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
// RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
// RFC3339 = "2006-01-02T15:04:05Z07:00"
// RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
// Kitchen = "3:04PM"
// // Handy time stamps.
// Stamp = "Jan _2 15:04:05"
// StampMilli = "Jan _2 15:04:05.000"
// StampMicro = "Jan _2 15:04:05.000000"
// StampNano = "Jan _2 15:04:05.000000000"
func NewCustomTime(s int64, format string) CustomTime {
return CustomTime{
protocol: protocol{
Time: time.Unix(s, 0),
Valid: true,
},
Format: format,
}
}
// new custom format of time from time.Time
func NewCustomTimeFrom(t time.Time, format string) CustomTime {
return CustomTime{
protocol: protocol{
Time: t,
Valid: true,
},
Format: format,
}
}
// new custom format of time right now
func NewCustomTimeNow(format string) CustomTime {
return CustomTime{
protocol: protocol{
Time: time.Now(),
Valid: true,
},
Format: format,
}
}
// MarshalJSON implements json.Marshaler.
// It will encode null if this time is null.
func (t CustomTime) MarshalJSON() ([]byte, error) {
if !t.Valid {
return []byte("null"), nil
}
var stamp = fmt.Sprintf("\"%s\"", t.Time.Format(t.Format))
return []byte(stamp), nil
}

@ -0,0 +1,25 @@
package formatime
import (
"encoding/json"
"log"
"testing"
)
type joo struct {
Name string `json:"name"`
CreatedAt CustomTime `json:"created_at"`
}
func Test_customize(t *testing.T) {
b := joo{
Name: "Joo",
CreatedAt: NewCustomTimeNow("Jan _2 15:04:05.000000000"),
}
text, err := json.Marshal(&b)
if err != nil {
t.Fatal(err)
} else {
log.Print(string(text))
}
}

@ -0,0 +1,49 @@
package formatime
import (
"fmt"
"time"
)
// Date is a nullable time.Time. It supports SQL, JSON serialization AND datetime format(2006-01-02).
// It will marshal to null if null.
type Date struct {
protocol
}
const _DateFormat = "2006-01-02"
// new Date format of time, s is timestamp
func NewDate(s int64) Date {
return Date{protocol{
Time: time.Unix(s, 0),
Valid: true,
}}
}
// new Date format of time right now
func NewDateNow() Date {
return Date{protocol{
Time: time.Now(),
Valid: true,
}}
}
// new Date format of time from time.Time
func NewDateFrom(t time.Time) Date {
return Date{protocol{
Time: t,
Valid: true,
}}
}
// MarshalJSON implements json.Marshaler.
// It will encode null if this time is null.
func (t Date) MarshalJSON() ([]byte, error) {
if !t.Valid {
return []byte("null"), nil
}
var stamp = fmt.Sprintf("\"%s\"", t.Time.Format(_DateFormat))
return []byte(stamp), nil
}

@ -0,0 +1,48 @@
package formatime
import (
"fmt"
"time"
)
// Hour is a nullable time.Time. It supports SQL, JSON serialization AND datetime format(2006-01-02 15).
// It will marshal to null if null.
type Hour struct {
protocol
}
const _HourFormat = "2006-01-02 15"
// new Hour format of time, s is timestamp
func NewHour(s int64) Hour {
return Hour{protocol{
Time: time.Unix(s, 0),
Valid: true,
}}
}
// new Hour format of time right now
func NewHourNow() Hour {
return Hour{protocol{
Time: time.Now(),
Valid: true,
}}
}
// new Hour format of time from time.Time
func NewHourFrom(t time.Time) Hour {
return Hour{protocol{
Time: t,
Valid: true,
}}
}
// MarshalJSON implements json.Marshaler.
// It will encode null if this time is null.
func (t Hour) MarshalJSON() ([]byte, error) {
if !t.Valid {
return []byte("null"), nil
}
var stamp = fmt.Sprintf("\"%s\"", t.Time.Format(_HourFormat))
return []byte(stamp), nil
}

@ -0,0 +1,48 @@
package formatime
import (
"fmt"
"time"
)
// Minute is a nullable time.Time. It supports SQL, JSON serialization AND datetime format(2006-01-02 15).
// It will marshal to null if null.
type Minute struct {
protocol
}
const _MinuteFormat = "2006-01-02 15:04"
// new Minute format of time, s is timestamp
func NewMinute(s int64) Minute {
return Minute{protocol{
Time: time.Unix(s, 0),
Valid: true,
}}
}
// new Minute format of time right now
func NewMinuteNow() Minute {
return Minute{protocol{
Time: time.Now(),
Valid: true,
}}
}
// new Minute format of time from time.Time
func NewMinuteFrom(t time.Time) Minute {
return Minute{protocol{
Time: t,
Valid: true,
}}
}
// MarshalJSON implements json.Marshaler.
// It will encode null if this time is null.
func (t Minute) MarshalJSON() ([]byte, error) {
if !t.Valid {
return []byte("null"), nil
}
var stamp = fmt.Sprintf("\"%s\"", t.Time.Format(_MinuteFormat))
return []byte(stamp), nil
}

@ -0,0 +1,49 @@
package formatime
import (
"fmt"
"time"
)
// Second is a nullable time.Time. It supports SQL, JSON serialization AND datetime format(2006-01-02 15:04:05).
// It will marshal to null if null.
type Second struct {
protocol
}
const _SecondFormat = "2006-01-02 15:04:05"
// new Second format of time, s is timestamp
func NewSecond(s int64) Second {
return Second{protocol{
Time: time.Unix(s, 0),
Valid: true,
}}
}
// new Second format of time right now
func NewSecondNow() Second {
return Second{protocol{
Time: time.Now(),
Valid: true,
}}
}
// new Second format of time from time.Time
func NewSecondFrom(t time.Time) Second {
return Second{protocol{
Time: t,
Valid: true,
}}
}
// MarshalJSON implements json.Marshaler.
// It will encode null if this time is null.
func (t Second) MarshalJSON() ([]byte, error) {
if !t.Valid {
return []byte("null"), nil
}
var stamp = fmt.Sprintf("\"%s\"", t.Time.Format(_SecondFormat))
return []byte(stamp), nil
}

@ -0,0 +1,46 @@
package formatime
import (
"fmt"
"time"
)
// Timestamp is a nullable time.Time. It supports SQL, JSON serialization AND timestamp format.
// It will marshal to null if null.
type Timestamp struct {
protocol
}
// new timestamp format of time
func NewTimestamp(s int64) Timestamp {
return Timestamp{protocol{
Time: time.Unix(s, 0),
Valid: true,
}}
}
// new timestamp format of time right now
func NewTimestampNow() Timestamp {
return Timestamp{protocol{
Time: time.Now(),
Valid: true,
}}
}
// new timestamp format of time from time.Time
func NewTimestampFrom(t time.Time) Timestamp {
return Timestamp{protocol{
Time: t,
Valid: true,
}}
}
// MarshalJSON implements json.Marshaler.
// It will encode null if this time is null.
func (t Timestamp) MarshalJSON() ([]byte, error) {
if !t.Valid {
return []byte("null"), nil
}
var stamp = fmt.Sprintf("\"%d\"", t.Time.Unix())
return []byte(stamp), nil
}

@ -0,0 +1,26 @@
package formatime
import (
"encoding/json"
"log"
"testing"
)
type boo struct {
Name string `json:"name"`
CreatedAt Timestamp `json:"created_at"`
}
func Test_timestamp(t *testing.T) {
b := boo{
Name: "Boo",
CreatedAt: NewTimestampNow(),
}
jsonText, err := json.Marshal(&b)
if err != nil {
t.Fatal(err)
} else {
log.Print(string(jsonText))
}
}

@ -0,0 +1,98 @@
package formatime
import (
"database/sql/driver"
"encoding/json"
"fmt"
"reflect"
"time"
)
// protocol is a nullable time.Time. It supports SQL and JSON serialization.
// It will marshal to null if null.
type protocol struct {
Time time.Time
Valid bool
}
// Scan implements the Scanner interface.
func (t *protocol) Scan(value interface{}) error {
var err error
switch x := value.(type) {
case time.Time:
t.Time = x
case nil:
t.Valid = false
return nil
default:
err = fmt.Errorf("null: cannot scan type %T into null.Time: %v", value, value)
}
t.Valid = err == nil
return err
}
// Value implements the driver Valuer interface.
func (t protocol) Value() (driver.Value, error) {
if !t.Valid {
return nil, nil
}
return t.Time, nil
}
// IsZero returns true for invalid Times, hopefully for future omitempty support.
// A non-null Time with a zero value will not be considered zero.
func (t protocol) IsZero() bool {
return !t.Valid
}
// UnmarshalJSON implements json.Unmarshaler.
// It supports string, object (e.g. pq.NullTime and friends)
// and null input.
func (t *protocol) UnmarshalJSON(data []byte) error {
var err error
var v interface{}
if err = json.Unmarshal(data, &v); err != nil {
return err
}
switch x := v.(type) {
case string:
err = t.Time.UnmarshalJSON(data)
case map[string]interface{}:
ti, tiOK := x["Time"].(string)
valid, validOK := x["Valid"].(bool)
if !tiOK || !validOK {
return fmt.Errorf(`json: unmarshalling object into Go value of type null.Time requires key "Time" to be of type string and key "Valid" to be of type bool; found %T and %T, respectively`, x["Time"], x["Valid"])
}
err = t.Time.UnmarshalText([]byte(ti))
t.Valid = valid
return err
case nil:
t.Valid = false
return nil
default:
err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Time", reflect.TypeOf(v).Name())
}
t.Valid = err == nil
return err
}
// Marshal
func (t protocol) MarshalText() ([]byte, error) {
if !t.Valid {
return []byte("null"), nil
}
return t.Time.MarshalText()
}
func (t *protocol) UnmarshalText(text []byte) error {
str := string(text)
if str == "" || str == "null" {
t.Valid = false
return nil
}
if err := t.Time.UnmarshalText(text); err != nil {
return err
}
t.Valid = true
return nil
}
Loading…
Cancel
Save