github.com/go-chrono/chrono@v0.0.0-20240102183611-532f0d0d7c34/period_test.go (about) 1 package chrono_test 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/go-chrono/chrono" 8 ) 9 10 func TestPeriod_Format(t *testing.T) { 11 for _, tt := range []struct { 12 name string 13 input chrono.Period 14 expected string 15 }{ 16 { 17 name: "YMWD", 18 input: chrono.Period{Years: 14, Months: 8, Weeks: 4, Days: 2}, 19 expected: "P14Y8M4W2D", 20 }, 21 { 22 name: "YMW", 23 input: chrono.Period{Years: 14, Months: 8, Weeks: 4}, 24 expected: "P14Y8M4W", 25 }, 26 { 27 name: "YM", 28 input: chrono.Period{Years: 14, Months: 8}, 29 expected: "P14Y8M", 30 }, 31 { 32 name: "Y", 33 input: chrono.Period{Years: 14}, 34 expected: "P14Y", 35 }, 36 { 37 name: "YWD", 38 input: chrono.Period{Years: 14, Weeks: 4, Days: 2}, 39 expected: "P14Y4W2D", 40 }, 41 { 42 name: "YW", 43 input: chrono.Period{Years: 14, Weeks: 4}, 44 expected: "P14Y4W", 45 }, 46 { 47 name: "YMD", 48 input: chrono.Period{Years: 14, Months: 8, Days: 2}, 49 expected: "P14Y8M2D", 50 }, 51 { 52 name: "YD", 53 input: chrono.Period{Years: 14, Days: 2}, 54 expected: "P14Y2D", 55 }, 56 { 57 name: "MWD", 58 input: chrono.Period{Months: 8, Weeks: 4, Days: 2}, 59 expected: "P8M4W2D", 60 }, 61 { 62 name: "MW", 63 input: chrono.Period{Months: 8, Weeks: 4}, 64 expected: "P8M4W", 65 }, 66 { 67 name: "M", 68 input: chrono.Period{Months: 8}, 69 expected: "P8M", 70 }, 71 { 72 name: "MD", 73 input: chrono.Period{Months: 8, Days: 2}, 74 expected: "P8M2D", 75 }, 76 { 77 name: "WD", 78 input: chrono.Period{Weeks: 4, Days: 2}, 79 expected: "P4W2D", 80 }, 81 { 82 name: "D", 83 input: chrono.Period{Days: 2}, 84 expected: "P2D", 85 }, 86 { 87 name: "empty", 88 input: chrono.Period{}, 89 expected: "P0D", 90 }, 91 } { 92 t.Run(tt.name, func(t *testing.T) { 93 if out := tt.input.Format(); out != tt.expected { 94 t.Errorf("formatted period = %s, want %s", out, tt.expected) 95 } 96 }) 97 } 98 } 99 100 func TestPeriod_Parse(t *testing.T) { 101 for _, tt := range []struct { 102 name string 103 input string 104 expected chrono.Period 105 }{ 106 { 107 name: "valid YMWD", 108 input: "P14Y8M5W2D", 109 expected: chrono.Period{Years: 14, Months: 8, Weeks: 5, Days: 2}, 110 }, 111 { 112 name: "valid YMD", 113 input: "P14Y8M2D", 114 expected: chrono.Period{Years: 14, Months: 8, Days: 2}, 115 }, 116 { 117 name: "valid YM", 118 input: "P14Y8M", 119 expected: chrono.Period{Years: 14, Months: 8}, 120 }, 121 { 122 name: "valid YD", 123 input: "P14Y2D", 124 expected: chrono.Period{Years: 14, Days: 2}, 125 }, 126 { 127 name: "valid Y", 128 input: "P14Y", 129 expected: chrono.Period{Years: 14}, 130 }, 131 { 132 name: "valid MWD", 133 input: "P8M5W2D", 134 expected: chrono.Period{Months: 8, Weeks: 5, Days: 2}, 135 }, 136 { 137 name: "valid MW", 138 input: "P8M5W", 139 expected: chrono.Period{Months: 8, Weeks: 5}, 140 }, 141 { 142 name: "valid MD", 143 input: "P8M2D", 144 expected: chrono.Period{Months: 8, Days: 2}, 145 }, 146 { 147 name: "valid WD", 148 input: "P5W2D", 149 expected: chrono.Period{Weeks: 5, Days: 2}, 150 }, 151 { 152 name: "valid M", 153 input: "P8M", 154 expected: chrono.Period{Months: 8}, 155 }, 156 { 157 name: "valid W", 158 input: "P6W", 159 expected: chrono.Period{Weeks: 6}, 160 }, 161 { 162 name: "valid D", 163 input: "P2D", 164 expected: chrono.Period{Days: 2}, 165 }, 166 } { 167 t.Run(tt.name, func(t *testing.T) { 168 var p chrono.Period 169 if err := p.Parse(tt.input); err != nil { 170 t.Errorf("failed to parse period: %v", err) 171 } else if !p.Equal(tt.expected) { 172 t.Errorf("parsed period = %v, want %v", p, tt.expected) 173 } 174 }) 175 } 176 } 177 178 func TestParseDuration(t *testing.T) { 179 for _, tt := range []struct { 180 name string 181 input string 182 period chrono.Period 183 duration chrono.Duration 184 }{ 185 { 186 name: "period only", 187 input: "P2.5Y", 188 period: chrono.Period{Years: 2.5}, 189 duration: chrono.Duration{}, 190 }, 191 { 192 name: "duration only", 193 input: "PT6.5H", 194 period: chrono.Period{}, 195 duration: chrono.DurationOf((6 * chrono.Hour) + (30 * chrono.Minute)), 196 }, 197 { 198 name: "both period and duration", 199 input: "P2.5YT6.5H", 200 period: chrono.Period{Years: 2.5}, 201 duration: chrono.DurationOf((6 * chrono.Hour) + (30 * chrono.Minute)), 202 }, 203 } { 204 t.Run(tt.name, func(t *testing.T) { 205 run := func() { 206 if p, d, err := chrono.ParseDuration(tt.input); err != nil { 207 t.Errorf("failed to parse period & duration: %v", err) 208 } else if !p.Equal(tt.period) { 209 t.Errorf("parsed period = %v, want %v", p, tt.period) 210 } else if d.Compare(tt.duration) != 0 { 211 t.Errorf("parsed duration = %v, want %v", d, tt.duration) 212 } 213 } 214 215 t.Run("dots", func(t *testing.T) { 216 run() 217 }) 218 219 t.Run("commas", func(t *testing.T) { 220 tt.input = strings.ReplaceAll(tt.input, ".", ",") 221 run() 222 }) 223 }) 224 } 225 226 t.Run("invalid strings", func(t *testing.T) { 227 for _, tt := range []string{ 228 "P", 229 "PT", 230 } { 231 if _, _, err := chrono.ParseDuration(tt); err == nil { 232 t.Error("expecting error but got nil") 233 } 234 } 235 }) 236 }