أعتقد أن الكثيرين سيوافقون على أن العمل مع التواريخ في أي لغة برمجة تقريبًا يمثل صداعًا لا يصدق. التاريخ والوقت ليسا عشريين ، مناطق زمنية - يا إلهي ، لماذا لا يمكن أن تكون مجرد أعداد صحيحة - وبالطبع ، تنسيقات لا حصر لها من التاريخ والوقت. يمكنك ، بالطبع ، أن تجادل بأنهم يقولون أن هناك ISO 8601 وماذا تحتاج أيضًا إلى أحمق ، ولكن دعنا نواجه الأمر ، دعنا نقول - كم مرة واجهت الامتثال لهذا المعيار في واجهات برمجة تطبيقات الطرف الثالث؟ لا أعرف كيف تسير الأمور في الخارج مع هذا ، آمل أن يخبروني في التعليقات ، ولكن في توسعات ما بعد الاتحاد السوفيتي ، فإن الوضع هو المعانقة والبكاء. يستخدم كل منها شكله الخاص ، والملائم له فقط ، وتنسيق الوقت والتاريخ والتعامل معه كما تريد.
سأتحدث عن تجربتي الخاصة وعن الحل الموجود.
لم تكن المشكلة التي كنت أواجهها سيئة للغاية ، فقد كان تنسيق التاريخ في واجهة برمجة التطبيقات الذي كان عليّ التعامل معه يبدو كما يلي: YYYY-MM-DD hh: mm: ss . تبدو طبيعية ، أليس كذلك؟
لا.
غير طبيعي على الاطلاق.
لقد أدرك الأشخاص الملمون بصيغة ISO 8601 المصيد بالفعل. للتوضيح:
package main
import (
"encoding/json"
"log"
"time"
)
type Dated struct {
DateTime time.Time
}
func main() {
input := []byte("{\"datetime\": \"1900-01-01 12:00:04\"}")
var d Dated
err := json.Unmarshal(input, &d)
if err != nil {
log.Fatal(err)
}
}
نتيجة ماذا؟ هذا صحيح ، الخطأ هو:
parsing time ""1900-01-01 12:00:04"" as ""2006-01-02T15:04:05Z07:00"": cannot parse " 12:00:04"" as "T"
وهو أمر منطقي ، لأن Go يحتوي على عدد محدود من تنسيقات الوقت والتاريخ
التي يمكنه تحليلها:
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"
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"
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
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"
من هنا: https://golang.org/src/time/format.go
كما ترى ، التنسيق YYYY-MM-DD hh:mm:ss
غير موجود. حسنًا ، المشكلة واضحة ، ولكن ماذا أفعل بعد ذلك؟
, , Go json.Unmarshall
. — , JSON, , , UnmasrhallJSON,
.
, ,
, Unmarshaler, UnmasrhallJSON:
type CustomDate struct {
time.Time
}
func (c *CustomDate) UnmarshalJSON(b []byte) (err error) {
layout := "2006-01-02 15:04:05"
s := strings.Trim(string(b), "\"")
if s == "null" {
return
}
c.Time, err = time.Parse(layout, s)
return
}
type Dated struct {
DateTime CustomDate
}
, , API, , , . :
package main
import (
"encoding/json"
"fmt"
"log"
"strings"
"time"
)
type CustomDate struct {
time.Time
}
const layout = "2006-01-02 15:04:05"
func (c *CustomDate) UnmarshalJSON(b []byte) (err error) {
s := strings.Trim(string(b), `"`)
if s == "null" {
return
}
c.Time, err = time.Parse(layout, s)
return
}
func (c CustomDate) MarshalJSON() ([]byte, error) {
if c.Time.IsZero() {
return nil, nil
}
return []byte(fmt.Sprintf(`"%s"`, c.Time.Format(layout))), nil
}
type Dated struct {
DateTime CustomDate
}
func main() {
input := []byte("{\"datetime\": \"1900-01-01 12:00:04\"}")
var d Dated
err := json.Unmarshal(input, &d)
if err != nil {
log.Fatal(err)
}
log.Println("Unmarshal:")
log.Println(d.DateTime)
b, err := json.Marshal(d)
if err != nil {
log.Fatal(err)
}
log.Println("Marshal:")
log.Println(string(b))
}
Marshal/Unmarshal. — MarchalJSON , UnmarshalJSON —
:
Unmarshal:
1900-01-01 12:00:04 +0000 UTC
Marshal:
{"DateTime":"1900-01-01T12:00:04Z"}
, , .
Go — , , /, , ; — .
إذا كنت على استعداد لتقديم طرق أخرى مثيرة للاهتمام لحل هذه المشكلة - سأكون سعيدًا برؤيتها في التعليقات. حسنًا ، في الختام ، أود أن أتمنى لك أقل للتعامل مع التنسيقات غير القياسية لأي شيء.
شكرا للجميع.