การจัดการเวลานั้นมีความซับซ้อน ความคลาดเคลื่อนที่ทั่วไปเกี่ยวกับเวลารวมถึงดังต่อไปนี้

  1. หนึ่งวันประกอบด้วย 24 ชั่วโมง
  2. หนึ่งชั่วโมงมี 60 นาที
  3. หนึ่งสัปดาห์ประกอบด้วย 7 วัน
  4. หนึ่งปีประกอบด้วย 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 ที่อาจเกิดขึ้นระหว่างช่วงเวลาทั้งสองนั้นให้ทราบด้วย