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