localtime.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package toml
  2. import (
  3. "fmt"
  4. "strings"
  5. "time"
  6. )
  7. // LocalDate represents a calendar day in no specific timezone.
  8. type LocalDate struct {
  9. Year int
  10. Month int
  11. Day int
  12. }
  13. // AsTime converts d into a specific time instance at midnight in zone.
  14. func (d LocalDate) AsTime(zone *time.Location) time.Time {
  15. return time.Date(d.Year, time.Month(d.Month), d.Day, 0, 0, 0, 0, zone)
  16. }
  17. // String returns RFC 3339 representation of d.
  18. func (d LocalDate) String() string {
  19. return fmt.Sprintf("%04d-%02d-%02d", d.Year, d.Month, d.Day)
  20. }
  21. // MarshalText returns RFC 3339 representation of d.
  22. func (d LocalDate) MarshalText() ([]byte, error) {
  23. return []byte(d.String()), nil
  24. }
  25. // UnmarshalText parses b using RFC 3339 to fill d.
  26. func (d *LocalDate) UnmarshalText(b []byte) error {
  27. res, err := parseLocalDate(b)
  28. if err != nil {
  29. return err
  30. }
  31. *d = res
  32. return nil
  33. }
  34. // LocalTime represents a time of day of no specific day in no specific
  35. // timezone.
  36. type LocalTime struct {
  37. Hour int // Hour of the day: [0; 24[
  38. Minute int // Minute of the hour: [0; 60[
  39. Second int // Second of the minute: [0; 60[
  40. Nanosecond int // Nanoseconds within the second: [0, 1000000000[
  41. Precision int // Number of digits to display for Nanosecond.
  42. }
  43. // String returns RFC 3339 representation of d.
  44. // If d.Nanosecond and d.Precision are zero, the time won't have a nanosecond
  45. // component. If d.Nanosecond > 0 but d.Precision = 0, then the minimum number
  46. // of digits for nanoseconds is provided.
  47. func (d LocalTime) String() string {
  48. s := fmt.Sprintf("%02d:%02d:%02d", d.Hour, d.Minute, d.Second)
  49. if d.Precision > 0 {
  50. s += fmt.Sprintf(".%09d", d.Nanosecond)[:d.Precision+1]
  51. } else if d.Nanosecond > 0 {
  52. // Nanoseconds are specified, but precision is not provided. Use the
  53. // minimum.
  54. s += strings.Trim(fmt.Sprintf(".%09d", d.Nanosecond), "0")
  55. }
  56. return s
  57. }
  58. // MarshalText returns RFC 3339 representation of d.
  59. func (d LocalTime) MarshalText() ([]byte, error) {
  60. return []byte(d.String()), nil
  61. }
  62. // UnmarshalText parses b using RFC 3339 to fill d.
  63. func (d *LocalTime) UnmarshalText(b []byte) error {
  64. res, left, err := parseLocalTime(b)
  65. if err == nil && len(left) != 0 {
  66. err = newDecodeError(left, "extra characters")
  67. }
  68. if err != nil {
  69. return err
  70. }
  71. *d = res
  72. return nil
  73. }
  74. // LocalDateTime represents a time of a specific day in no specific timezone.
  75. type LocalDateTime struct {
  76. LocalDate
  77. LocalTime
  78. }
  79. // AsTime converts d into a specific time instance in zone.
  80. func (d LocalDateTime) AsTime(zone *time.Location) time.Time {
  81. return time.Date(d.Year, time.Month(d.Month), d.Day, d.Hour, d.Minute, d.Second, d.Nanosecond, zone)
  82. }
  83. // String returns RFC 3339 representation of d.
  84. func (d LocalDateTime) String() string {
  85. return d.LocalDate.String() + "T" + d.LocalTime.String()
  86. }
  87. // MarshalText returns RFC 3339 representation of d.
  88. func (d LocalDateTime) MarshalText() ([]byte, error) {
  89. return []byte(d.String()), nil
  90. }
  91. // UnmarshalText parses b using RFC 3339 to fill d.
  92. func (d *LocalDateTime) UnmarshalText(data []byte) error {
  93. res, left, err := parseLocalDateTime(data)
  94. if err == nil && len(left) != 0 {
  95. err = newDecodeError(left, "extra characters")
  96. }
  97. if err != nil {
  98. return err
  99. }
  100. *d = res
  101. return nil
  102. }