การจัดการเวลานั้นมีความซับซ้อน ความคลาดเคลื่อนที่ทั่วไปเกี่ยวกับเวลารวมถึงดังต่อไปนี้
- หนึ่งวันประกอบด้วย 24 ชั่วโมง
- หนึ่งชั่วโมงมี 60 นาที
- หนึ่งสัปดาห์ประกอบด้วย 7 วัน
- หนึ่งปีประกอบด้วย 365 วัน
ตัวอย่างเช่น 1 บ่งชี้ว่าการเพิ่ม 24 ชั่วโมงในเวลาที่กำหนดไม่ได้ทำให้เกิดวันที่ต่างใหม่เสมอ
ดังนั้น ในการจัดการกับเวลา ควรใช้แพ็คเกจ "time"
เนื่องจากมันช่วยในการจัดการกับความคลาดเคลื่นที่ทั่วไปได้อย่างปลอดภัยและแม่นยำมากขึ้น
การใช้ time.Time
เพื่อแทนเวลาทันที
เมื่อจัดการกับเวลาทันที ควรใช้ time.Time
และเมธอดของมันในการเปรียบเทียบ เพิ่มหรือลดเวลา
ไม่แนะนำ:
func isActive(now, start, stop int) bool {
return start <= now && now < stop
}
แนะนำ:
func isActive(now, start, stop time.Time) bool {
return (start.Before(now) || start.Equal(now)) && now.Before(stop)
}
การใช้ time.Duration
เพื่อแทนระยะเวลา
เมื่อจัดการกับระยะเวลา ควรใช้ time.Duration
ไม่แนะนำ:
func poll(delay int) {
for {
// ...
time.Sleep(time.Duration(delay) * time.Millisecond)
}
}
poll(10) // เป็นวินาทีหรือมิลลิวินาที?
แนะนำ:
func poll(delay time.Duration) {
for {
// ...
time.Sleep(delay)
}
}
poll(10*time.Second)
เมื่อกลับมาที่ตัวอย่างแรก การเพิ่ม 24 ชั่วโมงในเวลาทันที ขึ้นอยู่กับความตั้งใจ หากต้องการจุดเวลาเดียวกันในวันที่ปฏิทินถัดไป (วันหลังจากวันปัจจุบัน) ควรใช้ Time.AddDate
อย่างไรก็ตามหากต้องการให้แน่ใจว่าช่วงเวลาหนึ่งเป็น 24 ชั่วโมงหลังจากก่อนหน้า ควรใช้ Time.Add
.
newDay := t.AddDate(0 /* years */, 0 /* months */, 1 /* days */)
maybeNewDay := t.Add(24 * time.Hour)
การใช้ time.Time
และ time.Duration
กับระบบภายนอก
เมื่อเป็นไปได้ ให้ใช้ time.Duration
และ time.Time
ในการโต้ตอบกับระบบภายนอก เช่น:
- ตัวอ้างอิงของ command-line flags:
flag
รองรับtime.Duration
ผ่านtime.ParseDuration
. - JSON:
encoding/json
รองรับการเข้ารหัสtime.Time
เป็นสตริง RFC 3339 โดยใช้เมธอดUnmarshalJSON
ของมัน. - SQL:
database/sql
รองรับการแปลงคอลัมน์DATETIME
หรือTIMESTAMP
เป็นtime.Time
และคืนค่าว่า driver ที่อยู่ภายในรองรับหรือไม่. - YAML:
gopkg.in/yaml.v2
รองรับการใช้time.Time
เป็นสตริง RFC 3339 และtime.Duration
ผ่านtime.ParseDuration
.
เมื่อ time.Duration
ไม่สามารถใช้ในการโต้ตอบเหล่านี้ได้ ให้ใช้ int
หรือ float64
และรวมหน่วยในชื่อฟิลด์ด้วย
ตัวอย่างเช่น เนื่องจาก encoding/json
ไม่รองรับ time.Duration
หน่วยถูกนำมาแต่งชื่อในฟิลด์ด้วย
ไม่แนะนำ:
// {"interval": 2}
type Config struct {
Interval int `json:"interval"`
}
แนะนำ:
// {"intervalMillis": 2000}
type Config struct {
IntervalMillis int `json:"intervalMillis"`
}
เมื่อ time.Time
ไม่สามารถใช้ในการโต้ตอบเหล่านี้ได้ นอกจากข้อตกลงอื่น ๆ ให้ใช้ string
และจัดรูปแบบ timestamp ตาม RFC 3339. โดยค่าเริ่มต้น Time.UnmarshalText
ใช้รูปแบบนี้และสามารถใช้กับ Time.Format
และ time.Parse
ผ่าน time.RFC3339
.
แม้ว่ามันจะไม่ได้เป็นปัญหาที่สำคัญ โปรดทราบว่า แพ็คเกจ "time"
ไม่รองรับการแปลง timestep ที่มี leap second (8728) และไม่คำนึงถึง leap second ในการคำนวณเวลา (15190). หากคุณเปรียบเทียบสองช่วงเวลา ความต่างจะไม่รวม leap second ที่อาจเกิดขึ้นระหว่างช่วงเวลาทั้งสองนั้นให้ทราบด้วย