├── .circleci
└── config.yml
├── .github
└── release-drafter.yml
├── .gitignore
├── LICENSE
├── README.md
├── datetime.go
├── datetime_test.go
├── docs
└── resources
│ └── logo.png
├── errors.go
├── errors_test.go
├── formats.go
├── formatting.go
├── formatting_test.go
├── go.mod
├── go.sum
├── timezone.go
├── timezone_constants.go
└── timezone_test.go
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | jobs:
4 | build:
5 | docker:
6 | - image: golang:1.17-alpine
7 | working_directory: /go/src/gostradamus
8 | steps:
9 | - checkout
10 | - run: go install github.com/bykof/gostradamus
11 |
12 | lint:
13 | docker:
14 | - image: golangci/golangci-lint:v1.43-alpine
15 | steps:
16 | - checkout
17 | - run: golangci-lint run
18 |
19 | test:
20 | docker:
21 | - image: golang:1.17
22 | working_directory: /go/src/gostradamus
23 | steps:
24 | - checkout
25 | - run: go test -v -race -cover -coverprofile coverage.txt -covermode=atomic ./...
26 | - run: bash <(curl -s https://codecov.io/bash)
27 |
28 | workflows:
29 | version: 2
30 | build_lint_test:
31 | jobs:
32 | - build
33 | - lint
34 | - test
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | # https://github.com/apps/release-drafter
2 | template: |
3 | ## What’s Changed
4 |
5 | $CHANGES
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, built with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | # Dependency directories (remove the comment below to include it)
15 | # vendor/
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Michael Bykovski
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Gostradamus: Better DateTimes for Go
6 |
7 | [](https://app.circleci.com/pipelines/github/bykof/gostradamus)
8 | [](https://goreportcard.com/report/github.com/bykof/gostradamus)
9 | [](https://codecov.io/gh/bykof/gostradamus)
10 | [](https://github.com/avelino/awesome-go)
11 | [](https://pkg.go.dev/github.com/bykof/gostradamus)
12 |
13 | ## Introduction
14 |
15 | Gostradamus is a Go library that offers a lightweight and human-friendly way to create, transform, format, and parse
16 | datetimes.
17 | It uses the underlying Go `time` library and the main gostradamus' type `DateTime` can be easily converted to and
18 | from `time.Time`.
19 |
20 | Gostradamus is named after the french pharmacist [Nostradamus](https://en.wikipedia.org/wiki/Nostradamus).
21 | He is known for his prophecies, therefore he worked a lot with time, like Gostradamus.
22 |
23 | ## Features
24 |
25 | ✅ Easy conversion between `time.Time` and `gostradamus.DateTime`
26 |
27 | ✅ Format with common and known format tokens like `YYYY-MM-DD HH:mm:ss`
28 |
29 | ✅ Generates time spans, floors, ceilings from second to year (weeks included)
30 |
31 | ✅ Weeks manipulation and helper functions
32 |
33 | ✅ Timezone-aware with conversion
34 |
35 | ✅ Fully tested and ready for production
36 |
37 | ## Basic Usage
38 |
39 | ```go
40 | package main
41 |
42 | import "github.com/bykof/gostradamus"
43 |
44 | func main() {
45 | // Easy parsing
46 | dateTime, err := gostradamus.Parse("14.07.2017 02:40:00", "DD.MM.YYYY HH:mm:ss")
47 | if err != nil {
48 | panic(err)
49 | }
50 |
51 | // Easy manipulation
52 | dateTime = dateTime.ShiftMonths(-5).ShiftDays(2)
53 |
54 | // Easy formatting
55 | println(dateTime.Format("DD.MM.YYYY HH:mm:ss"))
56 | // 16.02.2017 02:40:00
57 |
58 | // Easy helper functions
59 | start, end := dateTime.SpanWeek()
60 |
61 | println(start.String(), end.String())
62 | // 2017-02-13T00:00:00.000000Z 2017-02-19T23:59:59.999999Z
63 | }
64 | ```
65 |
66 | ## Table of Contents
67 |
68 | + [Types](#types)
69 | + [Conversion between time.Time and gostradamus.DateTime](#conversion-between-timetime-and-gostradamusdatetime)
70 | + [Creation](#creation)
71 | + [Timezones](#timezones)
72 | + [Shift](#shift)
73 | + [Replace](#replace)
74 | + [Token Table](#token-table)
75 | + [Parsing](#parsing)
76 | + [Formatting](#formatting)
77 | + [Floor](#floor)
78 | + [Ceil](#ceil)
79 | + [Spans](#spans)
80 | + [Utils](#utils)
81 | - [IsBetween](#isBetween)
82 | - [IsoCalendar](#isoCalendar)
83 | + [Contribution](#contribution)
84 | + [License](#license)
85 |
86 | ## Usage
87 |
88 | This part introduces all basic features of gostradamus.
89 | Surely there are more, just look them up in
90 | the [offical documentation](https://pkg.go.dev/github.com/bykof/gostradamus?tab=doc).
91 |
92 | ## Types
93 |
94 | There are two types in this package, which are important to know:
95 |
96 | ```go
97 | type DateTime time.Time
98 | type Timezone string
99 | ```
100 |
101 | `DateTime` contains all the creation, transforming, formatting and parsing functions.
102 |
103 | `Timezone` is just a string type but gostradamus has all timezones defined as constants.
104 | Look [here](https://github.com/bykof/gostradamus/blob/master/timezone_constants.go).
105 |
106 | ## Conversion between time.Time and gostradamus.DateTime
107 |
108 | You can easily convert between gostradamus.DateTime and time.Time package.
109 | Either with helper functions or with golang's [type conversion](https://tour.golang.org/basics/13)
110 |
111 | ```go
112 | import "time"
113 |
114 | // From gostradamus.DateTime to time.Time
115 | dateTime := gostradamus.Now()
116 | firstTime := dateTime.Time()
117 | secondTime := time.Time(dateTime)
118 |
119 | // From time.Time to gostradamus.DateTime
120 | t := time.Now()
121 | dateTime = gostradamus.DateTimeFromTime(t)
122 | dateTime = gostradamus.DateTime(t)
123 | ```
124 |
125 | ## Creation
126 |
127 | If you want to create a gostradamus.DateTime you have several ways:
128 |
129 | Just create the DateTime from scratch:
130 |
131 | ```go
132 | // Create it with a defined timezone as you know it
133 | dateTime := gostradamus.NewDateTime(2020, 1, 1, 12, 0, 0, 0, gostradamus.EuropeBerlin)
134 |
135 | // Create it with predefined UTC timezone
136 | dateTime := gostradamus.NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0)
137 |
138 | // Create it with local timzone
139 | dateTime := gostradamus.NewLocalDateTime(2020, 1, 1, 12, 0, 0, 0)
140 | ```
141 |
142 | Or create a DateTime from an ISO-8601 format:
143 |
144 | ```go
145 | dateTime := gostradamus.Parse("2017-07-14T02:40:00.000000+0200", gostradamus.Iso8601)
146 | ```
147 |
148 | Or from a custom format:
149 |
150 | ```go
151 | dateTime := gostradamus.Parse("10.02.2010 14:59:53", "DD.MM.YYYY HH:mm:ss")
152 | ```
153 |
154 | Or an UNIX timestamp for example:
155 |
156 | ```go
157 | dateTime := gostradamus.FromUnixTimestamp(1500000000)
158 | ```
159 |
160 | Or different ways of the current datetime:
161 |
162 | ```go
163 | // Current DateTime in local timezone
164 | dateTime := gostradamus.Now()
165 |
166 | // Current DateTime in UTC timezone
167 | dateTime = gostradamus.UTCNow()
168 |
169 | // Current DateTime in given timezone
170 | dateTime = gostradamus.NowInTimezone(gostradamus.EuropeParis)
171 | ```
172 |
173 | ## Timezones
174 |
175 | Feel free to use all available timezones,
176 | defined [here](https://github.com/bykof/gostradamus/blob/master/timezone_constants.go):
177 |
178 | ```go
179 | gostradamus.EuropeParis // Europe/Paris
180 | gostradamus.EuropeBerlin // Europe/Berlin
181 | gostradamus.AmericaNewYork // America/New_York
182 | ... and many more
183 | ```
184 |
185 | Convert between timezones easily:
186 |
187 | ```go
188 | dateTime := gostradamus.NewUTC(2020, 1, 1, 12, 12, 12, 0).InTimezone(gostradamus.EuropeBerlin)
189 | println(dateTime.String())
190 | // 2020-02-15T13:12:12.000000+0100
191 |
192 | dateTime = dateTime.InTimeZone(America_New_York)
193 | println(dateTime.String())
194 | // 2020-02-15T07:12:12.000000-0500
195 | ```
196 |
197 | ## Shift
198 |
199 | Shifting helps you to add or subtract years, months, days, hours, minutes, seconds, milliseconds, microseconds, and
200 | nanoseconds.
201 |
202 | To add a value use positive integer, to subtract use negative integer.
203 |
204 | ```go
205 | dateTime := gostradamus.NewUTCDateTime(2020, 1, 1, 1, 1, 1, 1)
206 | dateTime = dateTime.ShiftYears(10)
207 | println(dateTime.String())
208 | // 2030-01-01T01:01:01.000000+0000
209 |
210 | dateTime = gostradamus.NewUTCDateTime(2020, 1, 1, 1, 1, 1, 1)
211 | dateTime = dateTime.ShiftDays(-10)
212 | println(dateTime.String())
213 | // 2019-12-22T01:01:01.000000+0000
214 |
215 | dateTime = gostradamus.NewUTCDateTime(2020, 1, 1, 1, 1, 1, 1)
216 | dateTime = dateTime.ShiftWeeks(2)
217 | println(dateTime.String())
218 | // 2020-01-15T01:01:01.000000+0000
219 |
220 | dateTime = gostradamus.NewUTCDateTime(2020, 1, 1, 1, 1, 1, 1)
221 | dateTime = dateTime.Shift(0, 1, 10, 0, 0, 0, 0)
222 | println(dateTime.String())
223 | // 2020-02-11T01:01:01.000000+0000
224 | ```
225 |
226 | ## Replace
227 |
228 | Replacing values can be done easily.
229 |
230 | ```go
231 | dateTime := gostradamus.NewUTCDateTime(2020, 1, 1, 1, 1, 1, 1)
232 | dateTime = dateTime.ReplaceYear(2010)
233 | println(dateTime.String())
234 | // 2010-01-01T01:01:01.000000+0000
235 |
236 | dateTime = gostradamus.NewUTCDateTime(2020, 1, 1, 1, 1, 1, 1)
237 | dateTime = dateTime.ReplaceYear(2010).ReplaceMonth(2)
238 | println(dateTime.String())
239 | // 2010-02-01T01:01:01.000000+0000
240 | ```
241 |
242 | ## Token Table
243 |
244 | | | Token | Output |
245 | |----------------|---------|-------------------------------------------|
246 | | Year | YYYY | 2000, 2001, 2002 … 2012, 2013 |
247 | | | YY | 00, 01, 02 … 12, 13 |
248 | | Month | MMMM | January, February, March … |
249 | | | MMM | Jan, Feb, Mar … |
250 | | | MM | 01, 02, 03 … 11, 12 |
251 | | | M | 1, 2, 3 … 11, 12 |
252 | | Day of Year | DDDD | 001, 002, 003 … 364, 365 |
253 | | Day of Month | DD | 01, 02, 03 … 30, 31 |
254 | | | D | 1, 2, 3 … 30, 31 |
255 | | | Do | 1st, 2nd, 3rd … |
256 | | Day of Week | dddd | Monday, Tuesday, Wednesday … |
257 | | | ddd | Mon, Tue, Wed … |
258 | | Hour | HH | 00, 01, 02 … 23, 24 |
259 | | | hh | 01, 02, 03 … 11, 12 |
260 | | | h | 1, 2, 3 … 11, 12 |
261 | | AM / PM | A | AM, PM |
262 | | | a | am, pm |
263 | | Minute | mm | 00, 01, 02 … 58, 59 |
264 | | | m | 0, 1, 2 … 58, 59 |
265 | | Second | ss | 00, 01, 02 … 58, 59 |
266 | | | s | 0, 1, 2 … 58, 59 |
267 | | Microsecond | S | 000000 … 999999 |
268 | | Timezone | ZZZ | Asia/Baku, Europe/Warsaw, GMT |
269 | | | zz | -07:00, -06:00 … +06:00, +07:00, +08, Z |
270 | | | Z | -0700, -0600 … +0600, +0700, +08, Z |
271 |
272 | ## Parsing
273 |
274 | > Please consider that you cannot put custom tokens or custom letters into the *parsing* string
275 |
276 | Easily parse with `Parse`:
277 |
278 | ```go
279 | dateTime, err := gostradamus.Parse("10.02.2010 14:59:53", "DD.MM.YYYY HH:mm:ss")
280 | println(dateTime.String())
281 | // 2010-02-10T14:59:53.000000Z
282 | ```
283 |
284 | You can also specify a timezone while parsing:
285 |
286 | ```go
287 | dateTime, err := gostradamus.ParseInTimezone("10.02.2010 14:59:53", "DD.MM.YYYY HH:mm:ss", gostradamus.EuropeBerlin)
288 | println(dateTime.String())
289 | // 2010-02-10T14:59:53.000000+0100
290 | ```
291 |
292 | ## Formatting
293 |
294 | Formatting is as easy as parsing:
295 |
296 | ```go
297 | dateTimeString := gostradamus.NewDateTime(2017, 7, 14, 2, 40, 0, 0, UTC).Format("DD.MM.YYYY Time: HH:mm:ss")
298 | println(dateTimeString)
299 | // 14.07.2017 Time: 02:40:00
300 | ```
301 |
302 | ## Floor
303 |
304 | ```go
305 | dateTimeString := gostradamus.NewDateTime(2017, 7, 14, 2, 40, 0, 0, UTC).FloorDay()
306 | println(dateTimeString.String())
307 | // 2017-07-14T00:00:00.000000Z
308 |
309 | dateTimeString := gostradamus.NewDateTime(2017, 7, 14, 2, 40, 0, 0, UTC).FlorHour()
310 | println(dateTimeString.String())
311 | // 2017-07-14T02:00:00.000000Z
312 | ```
313 |
314 | ## Ceil
315 |
316 | ```go
317 | dateTimeString := gostradamus.NewDateTime(2017, 7, 14, 2, 40, 0, 0, UTC).CeilMonth()
318 | println(dateTimeString.String())
319 | // 2017-07-31T23:59:59.999999Z
320 |
321 | dateTimeString := gostradamus.NewDateTime(2017, 7, 14, 2, 40, 0, 0, UTC).CeilSecond()
322 | println(dateTimeString.String())
323 | // 2017-07-14T02:40:00.999999Z
324 | ```
325 |
326 | ## Spans
327 |
328 | Spans can help you to get quickly the current span of the month or the day:
329 |
330 | ```go
331 | start, end := NewDateTime(2017, 7, 14, 2, 40, 0, 0, UTC).SpanMonth()
332 | println(start.String())
333 | // 2017-07-01T00:00:00.000000Z
334 | println(end.String())
335 | // 2017-07-31T23:59:59.999999Z
336 |
337 | start, end = NewDateTime(2017, 7, 14, 2, 40, 0, 0, UTC).SpanDay()
338 | println(start.String())
339 | // 2017-07-14T00:00:00.000000Z
340 | println(end.String())
341 | // 2017-07-14T23:59:59.999999Z
342 |
343 | start, end = NewDateTime(2012, 12, 12, 2, 40, 0, 0, UTC).SpanWeek()
344 | println(start.String())
345 | // 2012-12-10T00:00:00.000000Z
346 | println(end.String())
347 | // 2012-12-16T23:59:59.999999Z
348 | ```
349 |
350 | ## Utils
351 |
352 | Here is the section for some nice helper functions that will save you some time.
353 |
354 | ### IsBetween
355 |
356 | ```go
357 | isBetween := gostradamus.NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).IsBetween(
358 | gostradamus.NewUTCDateTime(2020, 1, 1, 11, 0, 0, 0),
359 | gostradamus.NewUTCDateTime(2020, 1, 1, 13, 0, 0, 0),
360 | )
361 | println(isBetween)
362 | // true
363 |
364 | isBetween = gostradamus.NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).IsBetween(
365 | gostradamus.NewUTCDateTime(2020, 1, 1, 13, 0, 0, 0),
366 | gostradamus.NewUTCDateTime(2020, 1, 1, 14, 0, 0, 0),
367 | )
368 | println(isBetween)
369 | // false
370 | ```
371 |
372 | ### IsoCalendar
373 |
374 | Retrieve year, month, day directly as a 3-tuple:
375 |
376 | ```go
377 | year, month, day := gostradamus.NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).IsoCalendar()
378 | println(year, month, day)
379 | // 2020 1 1
380 | ```
381 |
382 | ## Contribution
383 |
384 | Do you have an idea to improve Gostradamus? -> [Create an issue](https://github.com/bykof/gostradamus/issues/new/choose)
385 |
386 | Do you have already coded something for Gostradamus? -> Create a pull request.
387 |
388 | Did you discover a bug? -> [Create an issue](https://github.com/bykof/gostradamus/issues/new/choose)
389 |
390 | Otherwise feel free to contact me: `michael@bykovski.de` or visit my webpage: [bykovski.de](https://bykovski.de)
391 |
392 | ## License
393 |
394 | MIT licensed. See the LICENSE file for details.
395 |
396 |
397 |
398 |
399 |
400 |
--------------------------------------------------------------------------------
/datetime.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | )
7 |
8 | // WeekInDays is the integer value how many days a week has
9 | const WeekInDays = 7
10 |
11 | // DateTime reflects time.Time and adds functionality of this library
12 | type DateTime time.Time
13 |
14 | // DateTimeFromTime returns a DateTime with given time.Time
15 | func DateTimeFromTime(time time.Time) DateTime {
16 | return DateTime(time)
17 | }
18 |
19 | // NewDateTime returns a new DateTime in the timezone given
20 | func NewDateTime(
21 | year int,
22 | month int,
23 | day int,
24 | hour int,
25 | minute int,
26 | second int,
27 | nanosecond int,
28 | timezone Timezone,
29 | ) DateTime {
30 | return DateTimeFromTime(
31 | time.Date(
32 | year,
33 | time.Month(month),
34 | day,
35 | hour,
36 | minute,
37 | second,
38 | nanosecond,
39 | timezone.Location(),
40 | ),
41 | )
42 | }
43 |
44 | // NewUTCDateTime returns a new DateTime with timezone in UTC
45 | func NewUTCDateTime(
46 | year int,
47 | month int,
48 | day int,
49 | hour int,
50 | minute int,
51 | second int,
52 | nanosecond int,
53 | ) DateTime {
54 | return NewDateTime(
55 | year,
56 | month,
57 | day,
58 | hour,
59 | minute,
60 | second,
61 | nanosecond,
62 | UTC,
63 | )
64 | }
65 |
66 | // NewLocalDateTime creates a new DateTime in Local (system) timezone
67 | func NewLocalDateTime(
68 | year int,
69 | month int,
70 | day int,
71 | hour int,
72 | minute int,
73 | second int,
74 | nanosecond int,
75 | ) DateTime {
76 | return NewDateTime(
77 | year,
78 | month,
79 | day,
80 | hour,
81 | minute,
82 | second,
83 | nanosecond,
84 | Local(),
85 | )
86 | }
87 |
88 | // FromUnixTimestamp gets the DateTime from given unix timestamp.
89 | // The returned Datetime has the UTC timezone
90 | func FromUnixTimestamp(timestamp int64) DateTime {
91 | return DateTime(time.Unix(timestamp, 0).UTC())
92 | }
93 |
94 | // Now returns the current local DateTime
95 | func Now() DateTime {
96 | return DateTimeFromTime(time.Now())
97 | }
98 |
99 | // UTCNow returns the current DateTime in UTC timezone
100 | func UTCNow() DateTime {
101 | return Now().InTimezone(UTC)
102 | }
103 |
104 | // NowInTimezone returns the current DateTime in given timezone
105 | func NowInTimezone(timezone Timezone) DateTime {
106 | return Now().InTimezone(timezone)
107 | }
108 |
109 | // Year of current DateTime as int
110 | func (dt DateTime) Year() int {
111 | return dt.Time().Year()
112 | }
113 |
114 | // Month of current DateTime as int
115 | func (dt DateTime) Month() int {
116 | return int(dt.Time().Month())
117 | }
118 |
119 | // Day of current DateTime as int
120 | func (dt DateTime) Day() int {
121 | return dt.Time().Day()
122 | }
123 |
124 | // Hour of current DateTime as int
125 | func (dt DateTime) Hour() int {
126 | return dt.Time().Hour()
127 | }
128 |
129 | // Minute of current DateTime as int
130 | func (dt DateTime) Minute() int {
131 | return dt.Time().Minute()
132 | }
133 |
134 | // Second of current DateTime as int
135 | func (dt DateTime) Second() int {
136 | return dt.Time().Second()
137 | }
138 |
139 | // Nanosecond of current DateTime as int
140 | func (dt DateTime) Nanosecond() int {
141 | return dt.Time().Nanosecond()
142 | }
143 |
144 | // Time returns the underlying time.Time of DateTime
145 | func (dt DateTime) Time() time.Time {
146 | return time.Time(dt)
147 | }
148 |
149 | // IsoFormat the current DateTime into ISO-8601 standard
150 | //
151 | // For Example:
152 | //
153 | // 2017-07-14T02:40:00.000000
154 | //
155 | func (dt DateTime) IsoFormat() string {
156 | return dt.Format(Iso8601)
157 | }
158 |
159 | // IsoFormatTZ the current DateTime into ISO-8601 standard and current timezone info
160 | //
161 | // For Example:
162 | //
163 | // 2017-07-14T02:40:00.000000+0200
164 | //
165 | func (dt DateTime) IsoFormatTZ() string {
166 | return dt.Format(Iso8601TZ)
167 | }
168 |
169 | // CTimeFormat the current DateTime to ctime standard
170 | //
171 | // Example: Sat Feb 15 12:12:12 2020
172 | //
173 | func (dt DateTime) CTimeFormat() string {
174 | return dt.Format(CTime)
175 | }
176 |
177 | // String of the DateTime
178 | // it will use the IsoFormat
179 | // It defines the ``native'' format for that value.
180 | // The String method is used to print values passed as an operand
181 | // to any format that accepts a string or to an unformatted printer
182 | // such as Print.
183 | func (dt DateTime) String() string {
184 | return dt.IsoFormatTZ()
185 | }
186 |
187 | // GoString of the DateTime
188 | // it will use the IsoFormat
189 | // The GoString method is used to print values passed as an operand to a %#v format.
190 | func (dt DateTime) GoString() string {
191 | return dt.IsoFormatTZ()
192 | }
193 |
194 | // Copy the current DateTime to a new DateTime
195 | func (dt DateTime) Copy() DateTime {
196 | return NewDateTime(
197 | dt.Year(),
198 | dt.Month(),
199 | dt.Day(),
200 | dt.Hour(),
201 | dt.Minute(),
202 | dt.Second(),
203 | dt.Nanosecond(),
204 | dt.Timezone(),
205 | )
206 | }
207 |
208 | // Format the current DateTime with given format to a string
209 | func (dt DateTime) Format(format string) string {
210 | return formatFromTime(dt.Time(), format)
211 | }
212 |
213 | // Parse a string value with given format into a new DateTime
214 | func Parse(value string, format string) (DateTime, error) {
215 | parsedTime, err := parseToTime(value, format, UTC)
216 | return DateTimeFromTime(parsedTime), err
217 | }
218 |
219 | // ParseInTimezone a string value with given format into a new DateTime in given timezone
220 | func ParseInTimezone(value string, format string, timezone Timezone) (DateTime, error) {
221 | parsedTime, err := parseToTime(value, format, timezone)
222 | return DateTimeFromTime(parsedTime), err
223 | }
224 |
225 | // InTimezone sets the current DateTime in the given Timezone and returns a new DateTime
226 | func (dt DateTime) InTimezone(timezone Timezone) DateTime {
227 | return DateTimeFromTime(dt.Time().In(timezone.Location()))
228 | }
229 |
230 | // IsoCalendar returns three int values with (year, month, day)
231 | func (dt DateTime) IsoCalendar() (int, int, int) {
232 | return dt.Year(), dt.Month(), dt.Day()
233 | }
234 |
235 | // Timezone returns the Timezone of current DateTime object
236 | func (dt DateTime) Timezone() Timezone {
237 | return Timezone(dt.Time().Location().String())
238 | }
239 |
240 | // UnixTimestamp returns the unix timestamp as int64
241 | func (dt DateTime) UnixTimestamp() int64 {
242 | return dt.Time().Unix()
243 | }
244 |
245 | // ShiftYears adds or subtracts years in current DateTime and returns a new DateTime
246 | // Add is a positive integer
247 | // Subtract is a negative integer
248 | func (dt DateTime) ShiftYears(years int) DateTime {
249 | return DateTimeFromTime(dt.Time().AddDate(years, 0, 0))
250 | }
251 |
252 | // ShiftMonths adds or subtracts months
253 | // Add is a positive integer
254 | // Subtract is a negative integer
255 | func (dt DateTime) ShiftMonths(months int) DateTime {
256 | return DateTimeFromTime(dt.Time().AddDate(0, months, 0))
257 | }
258 |
259 | // ShiftWeeks add or subtracts weeks
260 | // Add is a positive integer
261 | // Subtract is a negative integer
262 | func (dt DateTime) ShiftWeeks(weeks int) DateTime {
263 | return DateTimeFromTime(dt.Time().AddDate(0, 0, weeks*WeekInDays))
264 | }
265 |
266 | // ShiftDays adds or subtracts days
267 | // Add is a positive integer
268 | // Subtract is a negative integer
269 | func (dt DateTime) ShiftDays(days int) DateTime {
270 | return DateTimeFromTime(dt.Time().AddDate(0, 0, days))
271 | }
272 |
273 | // ShiftHours adds or subtracts hours
274 | // Add is a positive integer
275 | // Subtract is a negative integer
276 | func (dt DateTime) ShiftHours(hours int) DateTime {
277 | duration, _ := time.ParseDuration(fmt.Sprintf("%dh", hours))
278 | return DateTime(dt.Time().Add(duration))
279 | }
280 |
281 | // ShiftMinutes adds or subtracts minutes
282 | // Add is a positive integer
283 | // Subtract is a negative integer
284 | func (dt DateTime) ShiftMinutes(minutes int) DateTime {
285 | duration, _ := time.ParseDuration(fmt.Sprintf("%dm", minutes))
286 | return DateTime(dt.Time().Add(duration))
287 | }
288 |
289 | // ShiftSeconds adds or subtracts seconds
290 | // Add is a positive integer
291 | // Subtract is a negative integer
292 | func (dt DateTime) ShiftSeconds(second int) DateTime {
293 | duration, _ := time.ParseDuration(fmt.Sprintf("%ds", second))
294 | return DateTime(dt.Time().Add(duration))
295 | }
296 |
297 | // ShiftMilliSeconds adds or subtracts milliseconds
298 | // Add is a positive integer
299 | // Subtract is a negative integer
300 | func (dt DateTime) ShiftMilliSeconds(millisecond int) DateTime {
301 | duration, _ := time.ParseDuration(fmt.Sprintf("%dms", millisecond))
302 | return DateTime(dt.Time().Add(duration))
303 | }
304 |
305 | // ShiftMicroSeconds adds or subtracts microseconds
306 | // Add is a positive integer
307 | // Subtract is a negative integer
308 | func (dt DateTime) ShiftMicroSeconds(microsecond int) DateTime {
309 | duration, _ := time.ParseDuration(fmt.Sprintf("%dus", microsecond))
310 | return DateTime(dt.Time().Add(duration))
311 | }
312 |
313 | // ShiftNanoseconds adds or subtracts nanoseconds in current DateTime and returns a new DateTime
314 | // Add is a positive integer
315 | // Subtract is a negative integer
316 | func (dt DateTime) ShiftNanoseconds(nanosecond int) DateTime {
317 | duration, _ := time.ParseDuration(fmt.Sprintf("%dns", nanosecond))
318 | return DateTime(dt.Time().Add(duration))
319 | }
320 |
321 | // Shift adds or subtracts years, months, days, hours, minutes, seconds, and nanoseconds of current DateTime and returns a new DateTime
322 | // Add is a positive integer
323 | // Subtract is a negative integer
324 | func (dt DateTime) Shift(years int, months int, days int, hours int, minutes int, seconds int, nanoseconds int) DateTime {
325 | return dt.ShiftYears(years).
326 | ShiftMonths(months).
327 | ShiftDays(days).
328 | ShiftHours(hours).
329 | ShiftMinutes(minutes).
330 | ShiftSeconds(seconds).
331 | ShiftNanoseconds(nanoseconds)
332 | }
333 |
334 | // FloorYear returns a DateTime with all values to "floor" except year
335 | //
336 | // For Example:
337 | //
338 | // 2012-12-12 12:12:12.123456789 becomes 2012-01-01 00:00:00.00000000
339 | //
340 | func (dt DateTime) FloorYear() DateTime {
341 | return dt.Replace(dt.Year(), 1, 1, 0, 0, 0, 0)
342 | }
343 |
344 | // FloorMonth returns a DateTime with all values to "floor" except year, month
345 | //
346 | // For Example:
347 | //
348 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-01 00:00:00.00000000
349 | //
350 | func (dt DateTime) FloorMonth() DateTime {
351 | return dt.Replace(dt.Year(), dt.Month(), 1, 0, 0, 0, 0)
352 | }
353 |
354 | // FloorWeek returns a DateTime with all values to "floor" of current DateTime's week except year, month
355 | //
356 | // For Example:
357 | //
358 | // 2012-12-12 12:12:12.123456789 (wednesday) becomes 2012-12-10 00:00:00.000000000 (monday)
359 | //
360 | func (dt DateTime) FloorWeek() DateTime {
361 | deltaWeekdays := int(dt.WeekDay() - time.Monday)
362 | // currentWeekDay is already monday
363 | if deltaWeekdays == 0 {
364 | return dt.FloorDay()
365 | }
366 |
367 | if deltaWeekdays == -1 {
368 | return dt.ShiftDays(-6).FloorDay()
369 | }
370 |
371 | return dt.ShiftDays(-deltaWeekdays).FloorDay()
372 |
373 | }
374 |
375 | // FloorDay returns a DateTime with all values to "floor" except year, month, day
376 | //
377 | // For Example:
378 | //
379 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-12 00:00:00.00000000
380 | //
381 | func (dt DateTime) FloorDay() DateTime {
382 | return dt.Replace(dt.Year(), dt.Month(), dt.Day(), 0, 0, 0, 0)
383 | }
384 |
385 | // FloorHour returns a DateTime with all values to "floor" except year, month, day, hour
386 | //
387 | // For Example:
388 | //
389 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-12 12:00:00.00000000
390 | //
391 | func (dt DateTime) FloorHour() DateTime {
392 | return dt.Replace(dt.Year(), dt.Month(), dt.Day(), dt.Hour(), 0, 0, 0)
393 | }
394 |
395 | // FloorMinute returns a DateTime with all values to "floor" except year, month, day, hour, minute
396 | //
397 | // For Example:
398 | //
399 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-12 12:12:00.00000000
400 | //
401 | func (dt DateTime) FloorMinute() DateTime {
402 | return dt.Replace(dt.Year(), dt.Month(), dt.Day(), dt.Hour(), dt.Minute(), 0, 0)
403 | }
404 |
405 | // FloorSecond returns a DateTime with all values to "floor" except year, month, day, hour, minute, second
406 | //
407 | // For Example:
408 | //
409 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-31 12:12:12.00000000
410 | //
411 | func (dt DateTime) FloorSecond() DateTime {
412 | return dt.Replace(dt.Year(), dt.Month(), dt.Day(), dt.Hour(), dt.Minute(), dt.Second(), 0)
413 | }
414 |
415 | // CeilYear returns a DateTime with all values to "ceil" except year
416 | //
417 | // For Example:
418 | //
419 | // 2012-05-12 12:12:12.123456789 becomes 2012-12-31 23:59:59.999999999
420 | //
421 | func (dt DateTime) CeilYear() DateTime {
422 | return dt.Replace(dt.Year(), 12, 31, 23, 59, 59, 999999999)
423 | }
424 |
425 | // CeilMonth returns a DateTime with all values to "ceil" except year, month
426 | //
427 | // For Example:
428 | //
429 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-31 23:59:59.999999999
430 | //
431 | func (dt DateTime) CeilMonth() DateTime {
432 | tempDateTime := dt.Copy()
433 | tempDateTime = tempDateTime.ShiftMonths(1)
434 | tempDateTime = tempDateTime.ReplaceDay(1)
435 | tempDateTime = tempDateTime.ShiftDays(-1)
436 | return dt.Replace(dt.Year(), dt.Month(), tempDateTime.Day(), 23, 59, 59, 999999999)
437 | }
438 |
439 | // CeilWeek returns a DateTime with all values to "ceil" of current DateTime's week except year, month
440 | //
441 | // For Example:
442 | //
443 | // 2012-12-12 12:12:12.123456789 (wednesday) becomes 2012-12-16 23:59:59:123456789 (sunday)
444 | //
445 | func (dt DateTime) CeilWeek() DateTime {
446 | currentWeekDay := int(dt.WeekDay())
447 | if currentWeekDay == 0 {
448 | return dt.CeilDay()
449 | }
450 |
451 | return dt.ShiftDays(WeekInDays - currentWeekDay).CeilDay()
452 | }
453 |
454 | // CeilDay returns a DateTime with all values to "ceil" except year, month, day, minute, second
455 | //
456 | // For Example:
457 | //
458 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-12 23:59:59.999999999
459 | //
460 | func (dt DateTime) CeilDay() DateTime {
461 | return dt.Replace(dt.Year(), dt.Month(), dt.Day(), 23, 59, 59, 999999999)
462 | }
463 |
464 | // CeilHour returns a DateTime with all values to "ceil" except year, month, day, hour
465 | //
466 | // For Example:
467 | //
468 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-12 12:59:59.999999999
469 | //
470 | func (dt DateTime) CeilHour() DateTime {
471 | return dt.Replace(dt.Year(), dt.Month(), dt.Day(), dt.Hour(), 59, 59, 999999999)
472 | }
473 |
474 | // CeilMinute returns a DateTime with all values to "ceil" except year, month, day, hour, minute
475 | //
476 | // For Example:
477 | //
478 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-12 12:12:59.999999999
479 | //
480 | func (dt DateTime) CeilMinute() DateTime {
481 | return dt.Replace(dt.Year(), dt.Month(), dt.Day(), dt.Hour(), dt.Minute(), 59, 999999999)
482 | }
483 |
484 | // CeilSecond returns a DateTime with all values to "ceil" except year, month, day, hour, minute, second
485 | //
486 | // For Example:
487 | //
488 | // 2012-12-12 12:12:12.123456789 becomes 2012-12-12 12:12:12.999999999
489 | //
490 | func (dt DateTime) CeilSecond() DateTime {
491 | return dt.Replace(dt.Year(), dt.Month(), dt.Day(), dt.Hour(), dt.Minute(), dt.Second(), 999999999)
492 | }
493 |
494 | // SpanYear returns the start and end DateTime of current year span
495 | //
496 | // For Example:
497 | //
498 | // 2012-05-12 12:12:12:123456789 becomes (2012-01-01 00:00:00.000000000, 2012-12-31 23:59:59.999999999)
499 | //
500 | func (dt DateTime) SpanYear() (DateTime, DateTime) {
501 | return dt.FloorYear(), dt.CeilYear()
502 | }
503 |
504 | // SpanMonth returns the start and end DateTime of current month span
505 | //
506 | // For Example:
507 | //
508 | // 2012-12-12 12:12:12:123456789 becomes (2012-12-01 00:00:00.000000000, 2012-12-31 23:59:59.999999999)
509 | //
510 | func (dt DateTime) SpanMonth() (DateTime, DateTime) {
511 | return dt.FloorMonth(), dt.CeilMonth()
512 | }
513 |
514 | // SpanWeek returns the start and end DateTime of current week span
515 | //
516 | // For Example:
517 | //
518 | // 2012-12-12 12:12:12.123456789 becomes (2012-12-10 00:00:00.00000000, 2012-12-16 23:59:59.999999999)
519 | //
520 | func (dt DateTime) SpanWeek() (DateTime, DateTime) {
521 | return dt.FloorWeek(), dt.CeilWeek()
522 | }
523 |
524 | // SpanDay returns the start and end DateTime of current day span
525 | //
526 | // For Example:
527 | //
528 | // 2012-12-12 12:12:12:123456789 becomes (2012-12-12 00:00:00.000000000, 2012-12-12 23:59:59.999999999)
529 | //
530 | func (dt DateTime) SpanDay() (DateTime, DateTime) {
531 | return dt.FloorDay(), dt.CeilDay()
532 | }
533 |
534 | // SpanHour returns the start and end DateTime of current hour span
535 | //
536 | // For Example:
537 | //
538 | // 2012-12-12 12:12:12:123456789 becomes (2012-12-12 12:00:00.000000000, 2012-12-12 12:59:59.999999999)
539 | //
540 | func (dt DateTime) SpanHour() (DateTime, DateTime) {
541 | return dt.FloorHour(), dt.CeilHour()
542 | }
543 |
544 | // SpanMinute returns the start and end DateTime of current minute span
545 | //
546 | // For Example:
547 | //
548 | // 2012-12-12 12:12:12:123456789 becomes (2012-12-12 12:12:00.000000000, 2012-12-12 12:12:59.999999999)
549 | //
550 | func (dt DateTime) SpanMinute() (DateTime, DateTime) {
551 | return dt.FloorMinute(), dt.CeilMinute()
552 | }
553 |
554 | // SpanSecond returns the start and end DateTime of current second span
555 | //
556 | // For Example:
557 | //
558 | // 2012-12-12 12:12:12:123456789 becomes (2012-12-12 12:12:12.000000000, 2012-12-12 12:12:12.999999999)
559 | //
560 | func (dt DateTime) SpanSecond() (DateTime, DateTime) {
561 | return dt.FloorSecond(), dt.CeilSecond()
562 | }
563 |
564 | // WeekDay returns time.Weekday
565 | func (dt DateTime) WeekDay() time.Weekday {
566 | return dt.Time().Weekday()
567 | }
568 |
569 | // ReplaceYear will set the year of current DateTime and returns a new DateTime
570 | func (dt DateTime) ReplaceYear(year int) DateTime {
571 | return NewDateTime(
572 | year,
573 | dt.Month(),
574 | dt.Day(),
575 | dt.Hour(),
576 | dt.Minute(),
577 | dt.Second(),
578 | dt.Nanosecond(),
579 | dt.Timezone(),
580 | )
581 | }
582 |
583 | // ReplaceMonth will set the month of current DateTime and returns a new DateTime
584 | func (dt DateTime) ReplaceMonth(month int) DateTime {
585 | return NewDateTime(
586 | dt.Year(),
587 | month,
588 | dt.Day(),
589 | dt.Hour(),
590 | dt.Minute(),
591 | dt.Second(),
592 | dt.Nanosecond(),
593 | dt.Timezone(),
594 | )
595 | }
596 |
597 | // ReplaceDay will set the day of current DateTime and returns a new DateTime
598 | func (dt DateTime) ReplaceDay(day int) DateTime {
599 | return NewDateTime(
600 | dt.Year(),
601 | dt.Month(),
602 | day,
603 | dt.Hour(),
604 | dt.Minute(),
605 | dt.Second(),
606 | dt.Nanosecond(),
607 | dt.Timezone(),
608 | )
609 | }
610 |
611 | // ReplaceHour will set the hour of current DateTime and returns a new DateTime
612 | func (dt DateTime) ReplaceHour(hour int) DateTime {
613 | return NewDateTime(
614 | dt.Year(),
615 | dt.Month(),
616 | dt.Day(),
617 | hour,
618 | dt.Minute(),
619 | dt.Second(),
620 | dt.Nanosecond(),
621 | dt.Timezone(),
622 | )
623 | }
624 |
625 | // ReplaceMinute will set the minute of current DateTime and returns a new DateTime
626 | func (dt DateTime) ReplaceMinute(minute int) DateTime {
627 | return NewDateTime(
628 | dt.Year(),
629 | dt.Month(),
630 | dt.Day(),
631 | dt.Hour(),
632 | minute,
633 | dt.Second(),
634 | dt.Nanosecond(),
635 | dt.Timezone(),
636 | )
637 | }
638 |
639 | // ReplaceSecond will set the second of current DateTime and returns a new DateTime
640 | func (dt DateTime) ReplaceSecond(second int) DateTime {
641 | return NewDateTime(
642 | dt.Year(),
643 | dt.Month(),
644 | dt.Day(),
645 | dt.Hour(),
646 | dt.Minute(),
647 | second,
648 | dt.Nanosecond(),
649 | dt.Timezone(),
650 | )
651 | }
652 |
653 | // ReplaceNanosecond will set the nanosecond of current DateTime and returns a new DateTime
654 | func (dt DateTime) ReplaceNanosecond(nanosecond int) DateTime {
655 | return NewDateTime(
656 | dt.Year(),
657 | dt.Month(),
658 | dt.Day(),
659 | dt.Hour(),
660 | dt.Minute(),
661 | dt.Second(),
662 | nanosecond,
663 | dt.Timezone(),
664 | )
665 | }
666 |
667 | // Replace will set the year, month, day, hour, minute, second, and nanosecond of current DateTime and returns a new DateTime
668 | func (dt DateTime) Replace(year int, month int, day int, hour int, minute int, second int, nanosecond int) DateTime {
669 | return dt.ReplaceYear(year).
670 | ReplaceMonth(month).
671 | ReplaceDay(day).
672 | ReplaceHour(hour).
673 | ReplaceMinute(minute).
674 | ReplaceSecond(second).
675 | ReplaceNanosecond(nanosecond)
676 | }
677 |
678 | // IsBetween checks if current DateTime is between start and end DateTimes
679 | func (dt DateTime) IsBetween(start DateTime, end DateTime) bool {
680 | return dt.Time().After(start.Time()) && dt.Time().Before(end.Time())
681 | }
682 |
--------------------------------------------------------------------------------
/datetime_test.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | import (
4 | "github.com/stretchr/testify/assert"
5 | "testing"
6 | "time"
7 | )
8 |
9 | func TestParse(t *testing.T) {
10 | actual, err := Parse("10.02.2010 14:59:53", "DD.MM.YYYY HH:mm:ss")
11 | assert.NoError(t, err)
12 | assert.Equal(t, actual, NewUTCDateTime(2010, 2, 10, 14, 59, 53, 0))
13 |
14 | actual, err = Parse("2017-07-14T02:40:00.000000", Iso8601)
15 | assert.NoError(t, err)
16 | assert.Equal(t, NewDateTime(2017, 7, 14, 2, 40, 0, 0, UTC), actual)
17 | }
18 |
19 | func TestParseInTimezone(t *testing.T) {
20 | actual, err := ParseInTimezone("2017-07-14T02:40:00.000000+0200", Iso8601TZ, EuropeBerlin)
21 | assert.NoError(t, err)
22 | assert.Equal(
23 | t,
24 | NewDateTime(2017, 7, 14, 2, 40, 0, 0, EuropeBerlin),
25 | actual,
26 | )
27 | }
28 |
29 | func TestDateTime_ShiftMilliSeconds(t *testing.T) {
30 | dateTime := NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).ShiftMilliSeconds(10)
31 | assert.Equal(
32 | t,
33 | NewUTCDateTime(2020, 1, 1, 12, 0, 0, 10000000),
34 | dateTime,
35 | )
36 |
37 | dateTime = NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).ShiftMilliSeconds(0)
38 | assert.Equal(
39 | t,
40 | NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0),
41 | dateTime,
42 | )
43 |
44 | dateTime = NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).ShiftMilliSeconds(-20)
45 | assert.Equal(
46 | t,
47 | NewUTCDateTime(2020, 1, 1, 11, 59, 59, 980000000),
48 | dateTime,
49 | )
50 | }
51 |
52 | func TestDateTime_ShiftMicroSeconds(t *testing.T) {
53 | dateTime := NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).ShiftMicroSeconds(10)
54 | assert.Equal(
55 | t,
56 | NewUTCDateTime(2020, 1, 1, 12, 0, 0, 10000),
57 | dateTime,
58 | )
59 |
60 | dateTime = NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).ShiftMicroSeconds(0)
61 | assert.Equal(
62 | t,
63 | NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0),
64 | dateTime,
65 | )
66 |
67 | dateTime = NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).ShiftMicroSeconds(-20)
68 | assert.Equal(
69 | t,
70 | NewUTCDateTime(2020, 1, 1, 11, 59, 59, 999980000),
71 | dateTime,
72 | )
73 | }
74 |
75 | func TestDateTime_Shift(t *testing.T) {
76 | dateTime := NewUTCDateTime(2020, 1, 1, 12, 0, 1, 0).Shift(
77 | 10,
78 | 2,
79 | -3,
80 | -2,
81 | 20,
82 | 12,
83 | -20,
84 | )
85 | assert.Equal(
86 | t,
87 | NewUTCDateTime(2030, 2, 26, 10, 20, 12, 999999980),
88 | dateTime,
89 | )
90 | }
91 |
92 | func TestDateTime_Replace(t *testing.T) {
93 | dateTime := NewUTCDateTime(2020, 1, 1, 12, 0, 1, 0).Replace(
94 | 2030,
95 | 2,
96 | 26,
97 | 10,
98 | 20,
99 | 12,
100 | 999999980,
101 | )
102 | assert.Equal(
103 | t,
104 | NewUTCDateTime(2030, 2, 26, 10, 20, 12, 999999980),
105 | dateTime,
106 | )
107 | }
108 |
109 | func TestDateTime_WithTimezone(t *testing.T) {
110 |
111 | }
112 |
113 | func TestDateTime_Timezone(t *testing.T) {
114 | dateTime := NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0)
115 | assert.Equal(t, dateTime.Timezone(), UTC)
116 | }
117 |
118 | func TestFromUnixTimestamp(t *testing.T) {
119 | timestamp := int64(1500000000)
120 | actual := FromUnixTimestamp(timestamp)
121 | assert.Equal(t, NewUTCDateTime(2017, 7, 14, 2, 40, 0, 0), actual)
122 | }
123 |
124 | func TestDateTime_UnixTimestamp(t *testing.T) {
125 | actual := NewUTCDateTime(2017, 7, 14, 2, 40, 0, 0).UnixTimestamp()
126 | assert.Equal(t, actual, int64(1500000000))
127 | }
128 |
129 | func TestDateTime_ForJson(t *testing.T) {
130 | actual := NewUTCDateTime(2017, 7, 14, 2, 40, 0, 0).UnixTimestamp()
131 | assert.Equal(t, actual, int64(1500000000))
132 | }
133 |
134 | func TestNewLocalDateTime(t *testing.T) {
135 | actual := NewLocalDateTime(2017, 7, 14, 0, 40, 0, 0)
136 | _, offset := actual.Time().Zone()
137 | assert.Equal(
138 | t,
139 | actual,
140 | NewUTCDateTime(2017, 7, 14, actual.Hour()-(offset/3600), 40, 0, 0).InTimezone(Local()),
141 | )
142 | }
143 |
144 | func TestDateTime_IsoFormat(t *testing.T) {
145 | actual := NewDateTime(2017, 7, 14, 2, 40, 0, 0, EuropeBerlin).IsoFormat()
146 | assert.Equal(t, actual, "2017-07-14T02:40:00.000000")
147 | }
148 |
149 | func TestDateTime_String(t *testing.T) {
150 | actual := NewDateTime(2017, 7, 14, 2, 40, 0, 0, EuropeBerlin).String()
151 | assert.Equal(t, actual, "2017-07-14T02:40:00.000000+0200")
152 | }
153 |
154 | func TestDateTime_GoString(t *testing.T) {
155 | actual := NewDateTime(2017, 7, 14, 2, 40, 0, 0, EuropeBerlin).GoString()
156 | assert.Equal(t, actual, "2017-07-14T02:40:00.000000+0200")
157 | }
158 |
159 | func TestDateTime_IsBetween(t *testing.T) {
160 | actual := NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).IsBetween(
161 | NewUTCDateTime(2020, 1, 1, 11, 0, 0, 0),
162 | NewUTCDateTime(2020, 1, 1, 13, 0, 0, 0),
163 | )
164 | assert.True(t, actual)
165 |
166 | actual = NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).IsBetween(
167 | NewUTCDateTime(2020, 1, 1, 13, 0, 0, 0),
168 | NewUTCDateTime(2020, 1, 1, 14, 0, 0, 0),
169 | )
170 | assert.False(t, actual)
171 | }
172 |
173 | func TestDateTime_WeekDay(t *testing.T) {
174 | actual := NewUTCDateTime(2020, 1, 1, 12, 0, 0, 0).WeekDay()
175 | assert.Equal(t, actual, time.Wednesday)
176 | }
177 |
178 | func TestDateTime_IsoCalendar(t *testing.T) {
179 | year, month, day := NewUTCDateTime(2020, 12, 15, 12, 0, 0, 0).IsoCalendar()
180 | assert.Equal(t, year, 2020)
181 | assert.Equal(t, month, 12)
182 | assert.Equal(t, day, 15)
183 | }
184 |
185 | func TestDateTime_FloorYear(t *testing.T) {
186 | actual := NewUTCDateTime(2020, 12, 15, 12, 12, 49, 234).FloorYear()
187 | assert.Equal(t, NewUTCDateTime(2020, 1, 1, 0, 0, 0, 0), actual)
188 | }
189 |
190 | func TestDateTime_FloorMonth(t *testing.T) {
191 | actual := NewUTCDateTime(2020, 12, 15, 12, 12, 49, 234).FloorMonth()
192 | assert.Equal(t, NewUTCDateTime(2020, 12, 1, 0, 0, 0, 0), actual)
193 | }
194 |
195 | func TestDateTime_FloorWeek(t *testing.T) {
196 | // Weekday is already monday
197 | actual := NewUTCDateTime(2012, 12, 10, 12, 12, 49, 234).FloorWeek()
198 | assert.Equal(t, NewUTCDateTime(2012, 12, 10, 0, 0, 0, 0), actual)
199 |
200 | // Weekday is sunday
201 | actual = NewUTCDateTime(2012, 12, 16, 12, 12, 49, 234).FloorWeek()
202 | assert.Equal(t, NewUTCDateTime(2012, 12, 10, 0, 0, 0, 0), actual)
203 |
204 | // Weekday is other day
205 | actual = NewUTCDateTime(2012, 12, 12, 12, 12, 49, 234).FloorWeek()
206 | assert.Equal(t, NewUTCDateTime(2012, 12, 10, 0, 0, 0, 0), actual)
207 | }
208 |
209 | func TestDateTime_FloorDay(t *testing.T) {
210 | actual := NewUTCDateTime(2020, 12, 15, 12, 12, 49, 234).FloorDay()
211 | assert.Equal(t, NewUTCDateTime(2020, 12, 15, 0, 0, 0, 0), actual)
212 | }
213 |
214 | func TestDateTime_FloorHour(t *testing.T) {
215 | actual := NewUTCDateTime(2020, 12, 15, 12, 12, 49, 234).FloorHour()
216 | assert.Equal(t, NewUTCDateTime(2020, 12, 15, 12, 0, 0, 0), actual)
217 | }
218 |
219 | func TestDateTime_FloorMinute(t *testing.T) {
220 | actual := NewUTCDateTime(2020, 12, 15, 12, 12, 49, 234).FloorMinute()
221 | assert.Equal(t, NewUTCDateTime(2020, 12, 15, 12, 12, 0, 0), actual)
222 | }
223 |
224 | func TestDateTime_FloorSecond(t *testing.T) {
225 | actual := NewUTCDateTime(2020, 12, 15, 12, 12, 49, 234).FloorSecond()
226 | assert.Equal(t, NewUTCDateTime(2020, 12, 15, 12, 12, 49, 0), actual)
227 | }
228 |
229 | func TestDateTime_CeilYear(t *testing.T) {
230 | actual := NewUTCDateTime(2020, 12, 15, 12, 12, 49, 234).CeilYear()
231 | assert.Equal(t, NewUTCDateTime(2020, 12, 31, 23, 59, 59, 999999999), actual)
232 | }
233 |
234 | func TestDateTime_CeilMonth(t *testing.T) {
235 | actual := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).CeilMonth()
236 | assert.Equal(t, NewUTCDateTime(2020, 2, 29, 23, 59, 59, 999999999), actual)
237 | }
238 |
239 | func TestDateTime_CeilWeek(t *testing.T) {
240 | actual := NewUTCDateTime(2012, 12, 16, 12, 12, 49, 234).CeilWeek()
241 | assert.Equal(t, NewUTCDateTime(2012, 12, 16, 23, 59, 59, 999999999), actual)
242 |
243 | actual = NewUTCDateTime(2012, 12, 12, 12, 12, 49, 234).CeilWeek()
244 | assert.Equal(t, NewUTCDateTime(2012, 12, 16, 23, 59, 59, 999999999), actual)
245 | }
246 |
247 | func TestDateTime_CeilDay(t *testing.T) {
248 | actual := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).CeilDay()
249 | assert.Equal(t, NewUTCDateTime(2020, 2, 15, 23, 59, 59, 999999999), actual)
250 | }
251 |
252 | func TestDateTime_CeilHour(t *testing.T) {
253 | actual := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).CeilHour()
254 | assert.Equal(t, NewUTCDateTime(2020, 2, 15, 12, 59, 59, 999999999), actual)
255 | }
256 |
257 | func TestDateTime_CeilMinute(t *testing.T) {
258 | actual := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).CeilMinute()
259 | assert.Equal(t, NewUTCDateTime(2020, 2, 15, 12, 12, 59, 999999999), actual)
260 | }
261 |
262 | func TestDateTime_CeilSecond(t *testing.T) {
263 | actual := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).CeilSecond()
264 | assert.Equal(t, NewUTCDateTime(2020, 2, 15, 12, 12, 49, 999999999), actual)
265 | }
266 |
267 | func TestDateTime_SpanYear(t *testing.T) {
268 | start, end := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).SpanYear()
269 | assert.Equal(
270 | t,
271 | NewUTCDateTime(2020, 1, 1, 0, 0, 0, 00000000),
272 | start,
273 | )
274 | assert.Equal(
275 | t,
276 | NewUTCDateTime(2020, 12, 31, 23, 59, 59, 999999999),
277 | end,
278 | )
279 | }
280 |
281 | func TestDateTime_SpanMonth(t *testing.T) {
282 | start, end := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).SpanMonth()
283 | assert.Equal(
284 | t,
285 | NewUTCDateTime(2020, 2, 1, 0, 0, 0, 00000000),
286 | start,
287 | )
288 | assert.Equal(
289 | t,
290 | NewUTCDateTime(2020, 2, 29, 23, 59, 59, 999999999),
291 | end,
292 | )
293 | }
294 |
295 | func TestDateTime_SpanDay(t *testing.T) {
296 | start, end := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).SpanDay()
297 | assert.Equal(
298 | t,
299 | NewUTCDateTime(2020, 2, 15, 0, 0, 0, 00000000),
300 | start,
301 | )
302 | assert.Equal(
303 | t,
304 | NewUTCDateTime(2020, 2, 15, 23, 59, 59, 999999999),
305 | end,
306 | )
307 | }
308 |
309 | func TestDateTime_SpanHour(t *testing.T) {
310 | start, end := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).SpanHour()
311 | assert.Equal(
312 | t,
313 | NewUTCDateTime(2020, 2, 15, 12, 0, 0, 00000000),
314 | start,
315 | )
316 | assert.Equal(
317 | t,
318 | NewUTCDateTime(2020, 2, 15, 12, 59, 59, 999999999),
319 | end,
320 | )
321 | }
322 |
323 | func TestDateTime_SpanMinute(t *testing.T) {
324 | start, end := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).SpanMinute()
325 | assert.Equal(
326 | t,
327 | NewUTCDateTime(2020, 2, 15, 12, 12, 0, 00000000),
328 | start,
329 | )
330 | assert.Equal(
331 | t,
332 | NewUTCDateTime(2020, 2, 15, 12, 12, 59, 999999999),
333 | end,
334 | )
335 | }
336 |
337 | func TestDateTime_SpanSecond(t *testing.T) {
338 | start, end := NewUTCDateTime(2020, 2, 15, 12, 12, 49, 234).SpanSecond()
339 | assert.Equal(
340 | t,
341 | NewUTCDateTime(2020, 2, 15, 12, 12, 49, 00000000),
342 | start,
343 | )
344 | assert.Equal(
345 | t,
346 | NewUTCDateTime(2020, 2, 15, 12, 12, 49, 999999999),
347 | end,
348 | )
349 | }
350 |
351 | func TestDateTime_CTimeFormat(t *testing.T) {
352 | actual := NewUTCDateTime(2020, 2, 15, 12, 12, 12, 0).CTimeFormat()
353 | assert.Equal(
354 | t,
355 | "Sat Feb 15 12:12:12 2020",
356 | actual,
357 | )
358 | }
359 |
--------------------------------------------------------------------------------
/docs/resources/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bykof/gostradamus/5be648962cf65da5f9cac229b274f76e7b33fb1c/docs/resources/logo.png
--------------------------------------------------------------------------------
/errors.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | // FormatTokenIsNotMapped errors the given formatToken
8 | func FormatTokenIsNotMapped(formatToken string) error {
9 | return fmt.Errorf("FormatToken: %s is not mapped", formatToken)
10 | }
11 |
--------------------------------------------------------------------------------
/errors_test.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | import (
4 | "errors"
5 | "github.com/stretchr/testify/assert"
6 | "testing"
7 | )
8 |
9 | func TestFormatTokenIsNotMapped(t *testing.T) {
10 | actual := FormatTokenIsNotMapped("123")
11 | assert.Equal(
12 | t,
13 | errors.New("FormatToken: 123 is not mapped"),
14 | actual,
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/formats.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | const (
4 | // Iso8601 format
5 | //
6 | // Example: 2012-12-12T12:12:12.000000
7 | //
8 | Iso8601 = "YYYY-MM-DDTHH:mm:ss.S"
9 |
10 | // Iso8601TZ format with timezone
11 | //
12 | // Example with UTC: 2012-12-12T12:12:12.000000Z
13 | // Example with timezone: 2012-12-12T12:12:12.000000+0200
14 | //
15 | Iso8601TZ = "YYYY-MM-DDTHH:mm:ss.SZ"
16 |
17 | // CTime format with ctime standard
18 | //
19 | // Example: Sat Jan 19 18:26:50 2019
20 | //
21 | CTime = "ddd MMM DD HH:mm:ss YYYY"
22 | )
23 |
--------------------------------------------------------------------------------
/formatting.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | import (
4 | "regexp"
5 | "strings"
6 | "time"
7 |
8 | "github.com/dustin/go-humanize"
9 | )
10 |
11 | // All FormatTokens for parsing and formatting with DateTime
12 | const (
13 | YearFull = FormatToken("YYYY")
14 | YearShort = FormatToken("YY")
15 |
16 | MonthFull = FormatToken("MMMM")
17 | MonthAbbr = FormatToken("MMM")
18 | MonthZeroPadded = FormatToken("MM")
19 | MonthShort = FormatToken("M")
20 |
21 | DayOfYearZeroPadded = FormatToken("DDDD")
22 | DayOfMonthZeroPadded = FormatToken("DD")
23 | DayOfMonthShort = FormatToken("D")
24 | DayOfMonthOrdinal = FormatToken("Do")
25 |
26 | DayOfWeekFullName = FormatToken("dddd")
27 | DayOfWeekAbbr = FormatToken("ddd")
28 |
29 | TwentyFourHourZeroPadded = FormatToken("HH")
30 | TwelveHourZeroPadded = FormatToken("hh")
31 | TwelveHour = FormatToken("h")
32 |
33 | AMPMUpper = FormatToken("A")
34 | AMPMLower = FormatToken("a")
35 |
36 | MinuteZeroPadded = FormatToken("mm")
37 | Minute = FormatToken("m")
38 |
39 | SecondZeroPadded = FormatToken("ss")
40 | Second = FormatToken("s")
41 | MicroSecond = FormatToken("S")
42 |
43 | TimezoneFullName = FormatToken("ZZZ")
44 | TimezoneWithColon = FormatToken("zz")
45 | TimezoneWithoutColon = FormatToken("Z")
46 |
47 | GoLongMonth = goFormatToken("January")
48 | GoMonth = goFormatToken("Jan")
49 | GoNumMonth = goFormatToken("1")
50 | GoZeroMonth = goFormatToken("01")
51 | GoLongWeekDay = goFormatToken("Monday")
52 | GoWeekDay = goFormatToken("Mon")
53 | GoDay = goFormatToken("2")
54 | GoDayOrdinal = goFormatToken("Do")
55 | GoZeroDay = goFormatToken("02")
56 | GoZeroYearDay = goFormatToken("002")
57 | GoHour = goFormatToken("15")
58 | GoHour12 = goFormatToken("3")
59 | GoZeroHour12 = goFormatToken("03")
60 | GoMinute = goFormatToken("4")
61 | GoZeroMinute = goFormatToken("04")
62 | GoSecond = goFormatToken("5")
63 | GoZeroSecond = goFormatToken("05")
64 | GoLongYear = goFormatToken("2006")
65 | GoYear = goFormatToken("06")
66 | GoPM = goFormatToken("PM")
67 | Gopm = goFormatToken("pm")
68 | GoTZ = goFormatToken("MST")
69 | GoMillisecond = goFormatToken("000")
70 | GoMicrosecond = goFormatToken("000000")
71 | GoNanoSecond = goFormatToken("000000000")
72 | GoISO8601TZ = goFormatToken("Z0700") // prints Z for UTC
73 | GoISO8601SecondsTZ = goFormatToken("Z070000")
74 | GoISO8601ShortTZ = goFormatToken("Z07")
75 | GoISO8601ColonTZ = goFormatToken("Z07:00") // prints Z for UTC
76 | GoISO8601ColonSecondsTZ = goFormatToken("Z07:00:00")
77 | GoNumTZ = goFormatToken("-0700") // always numeric
78 | GoNumSecondsTz = goFormatToken("-070000")
79 | GoNumShortTZ = goFormatToken("-07") // always numeric
80 | GoNumColonTZ = goFormatToken("-07:00") // always numeric
81 | GoNumColonSecondsTZ = goFormatToken("-07:00:00")
82 | )
83 |
84 | // FormatToken helps to hold all possible tokens for parsing and formatting
85 | type FormatToken string
86 | type formatTokens []FormatToken
87 | type goFormatToken string
88 |
89 | var (
90 | formatTokenMap = map[FormatToken]goFormatToken{
91 | YearFull: GoLongYear,
92 | YearShort: GoYear,
93 | MonthFull: GoLongMonth,
94 | MonthAbbr: GoMonth,
95 | MonthZeroPadded: GoZeroMonth,
96 | MonthShort: GoNumMonth,
97 | DayOfYearZeroPadded: GoZeroYearDay,
98 | DayOfMonthZeroPadded: GoZeroDay,
99 | DayOfMonthShort: GoDay,
100 | DayOfWeekFullName: GoLongWeekDay,
101 | DayOfMonthOrdinal: GoDayOrdinal,
102 | DayOfWeekAbbr: GoWeekDay,
103 | TwentyFourHourZeroPadded: GoHour,
104 | TwelveHourZeroPadded: GoZeroHour12,
105 | TwelveHour: GoHour12,
106 | AMPMUpper: GoPM,
107 | AMPMLower: Gopm,
108 | MinuteZeroPadded: GoZeroMinute,
109 | Minute: GoMinute,
110 | SecondZeroPadded: GoZeroSecond,
111 | Second: GoSecond,
112 | MicroSecond: GoMicrosecond,
113 | TimezoneFullName: GoTZ,
114 | TimezoneWithColon: GoISO8601ColonTZ,
115 | TimezoneWithoutColon: GoISO8601TZ,
116 | }
117 |
118 | allFormatTokens = formatTokens{
119 | YearFull,
120 | YearShort,
121 | MonthFull,
122 | MonthAbbr,
123 | MonthZeroPadded,
124 | MonthShort,
125 | DayOfYearZeroPadded,
126 | DayOfMonthZeroPadded,
127 | DayOfMonthOrdinal,
128 | DayOfMonthShort,
129 | DayOfWeekFullName,
130 | DayOfWeekAbbr,
131 | TwentyFourHourZeroPadded,
132 | TwelveHourZeroPadded,
133 | TwelveHour,
134 | AMPMUpper,
135 | AMPMLower,
136 | MinuteZeroPadded,
137 | Minute,
138 | SecondZeroPadded,
139 | Second,
140 | MicroSecond,
141 | TimezoneFullName,
142 | TimezoneWithColon,
143 | TimezoneWithoutColon,
144 | }
145 | )
146 |
147 | func (fts formatTokens) toStringSlice() []string {
148 | var stringSlice []string
149 | for _, formatToken := range fts {
150 | stringSlice = append(stringSlice, string(formatToken))
151 | }
152 | return stringSlice
153 | }
154 |
155 | func formatTokenRegex() string {
156 | return strings.Join(allFormatTokens.toStringSlice(), "|")
157 | }
158 |
159 | // translateFormat translates all mapped formats to Go specific language
160 | func translateFormat(format string) string {
161 | re := regexp.MustCompile(formatTokenRegex())
162 | format = string(re.ReplaceAllFunc(
163 | []byte(format),
164 | func(bytes []byte) []byte {
165 | if goFormatToken, ok := formatTokenMap[FormatToken(bytes)]; ok {
166 | return []byte(goFormatToken)
167 | }
168 | panic(FormatTokenIsNotMapped(string(bytes)))
169 | },
170 | ))
171 |
172 | return format
173 | }
174 |
175 | // parseToTime parses the value with given format to a time.Time
176 | // error if the value could not be parsed
177 | //
178 | // parseToTime panics if the formatToken is not mapped correctly
179 | func parseToTime(value string, format string, timezone Timezone) (time.Time, error) {
180 | re := regexp.MustCompile(formatTokenRegex())
181 |
182 | format = string(re.ReplaceAllFunc(
183 | []byte(format),
184 | func(bytes []byte) []byte {
185 | if FormatToken(bytes) == FormatToken(DayOfMonthOrdinal) {
186 | // todo: prone to accidental replacements of said matches when used incidentally outside of 'Do' context
187 | replacer := strings.NewReplacer(
188 | "th", "",
189 | "rd", "",
190 | "st", "",
191 | "nd", "",
192 | )
193 |
194 | value = replacer.Replace(value)
195 |
196 | return []byte(DayOfMonthShort)
197 | }
198 |
199 | return bytes
200 | },
201 | ))
202 | format = translateFormat(format)
203 |
204 | return time.ParseInLocation(format, value, timezone.Location())
205 | }
206 |
207 | // formatFromTime formats value as time.Time with given format to a string
208 | func formatFromTime(value time.Time, format string) string {
209 | format = translateFormat(format)
210 |
211 | v := value.Format(format)
212 |
213 | v = strings.ReplaceAll(v, string(GoDayOrdinal), dayOrdinal(value))
214 |
215 | return v
216 | }
217 |
218 | func dayOrdinal(t time.Time) string {
219 | return humanize.Ordinal(t.Day())
220 | }
221 |
--------------------------------------------------------------------------------
/formatting_test.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | import (
4 | "testing"
5 | "time"
6 |
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func TestParseToTime(t *testing.T) {
11 | actualResult, err := parseToTime("2019-01-01 12:12:12", "YYYY-MM-DD HH:mm:ss", UTC)
12 | assert.NoError(t, err)
13 | assert.Equal(t, time.Date(2019, 1, 1, 12, 12, 12, 0, time.UTC), actualResult)
14 | }
15 |
16 | func TestParseToTime_Error(t *testing.T) {
17 | actualResult, err := parseToTime("2019-01-01 12:12:12", "YYYY-MM-DD testHH:mm:ss", UTC)
18 | assert.Error(t, err)
19 | assert.Equal(t, time.Time{}, actualResult)
20 | }
21 |
22 | func TestParseToTimeOrdinal(t *testing.T) {
23 | actualResult, err := parseToTime("Tuesday 5th April 2011", "dddd Do MMMM YYYY", UTC)
24 | assert.NoError(t, err)
25 | assert.Equal(t, time.Date(2011, 4, 5, 0, 0, 0, 0, time.UTC), actualResult)
26 | }
27 |
28 | func TestFormatFromTime(t *testing.T) {
29 | actualResult := formatFromTime(
30 | time.Date(2011, 4, 5, 15, 7, 8, 9, time.UTC),
31 | "YYYY YY MMMM MMM MM M DDDD DD D dddd ddd HH hh h A a mm m ss s S ZZZ zz Z",
32 | )
33 | assert.Equal(
34 | t,
35 | "2011 11 April Apr 04 4 095 05 5 Tuesday Tue 15 03 3 PM pm 07 7 08 8 000000 UTC Z Z",
36 | actualResult,
37 | )
38 |
39 | location, err := time.LoadLocation("Japan")
40 | if err != nil {
41 | panic(err)
42 | }
43 |
44 | date := time.Date(2011, 4, 5, 15, 7, 8, 9, location)
45 | actualResult = formatFromTime(
46 | date,
47 | "ZZZ zz Z",
48 | )
49 |
50 | assert.Equal(
51 | t,
52 | "JST +09:00 +0900",
53 | actualResult,
54 | )
55 | }
56 |
57 | func TestOrdinal(t *testing.T) {
58 | actualResult := formatFromTime(
59 | time.Date(2011, 4, 5, 15, 7, 8, 9, time.UTC),
60 | "dddd Do MMMM YYYY",
61 | )
62 | assert.Equal(
63 | t,
64 | "Tuesday 5th April 2011",
65 | actualResult,
66 | )
67 | }
68 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/bykof/gostradamus
2 |
3 | go 1.22
4 |
5 | require (
6 | github.com/dustin/go-humanize v1.0.1
7 | github.com/stretchr/testify v1.10.0
8 | )
9 |
10 | require (
11 | github.com/davecgh/go-spew v1.1.1 // indirect
12 | github.com/pmezard/go-difflib v1.0.0 // indirect
13 | gopkg.in/yaml.v3 v3.0.1 // indirect
14 | )
15 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3 | github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
4 | github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
8 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
10 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
11 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
12 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
13 |
--------------------------------------------------------------------------------
/timezone.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | import "time"
4 |
5 | // Timezone is a string type which can translate from and to time.Location
6 | type Timezone string
7 |
8 | // LoadLocation returns the time.Locatior or an error of a timezone
9 | func LoadLocation(timezone string) (*time.Location, error) {
10 | return time.LoadLocation(timezone)
11 | }
12 |
13 | // Local is a wrapper for "Local" as a Timezone
14 | func Local() Timezone {
15 | return Timezone(time.Local.String())
16 | }
17 |
18 | // Location returns the Location of current Timezone
19 | //
20 | // Location panics if current Timzeone does not exist
21 | func (t Timezone) Location() *time.Location {
22 | location, err := LoadLocation(t.String())
23 | if err != nil {
24 | panic(err)
25 | }
26 | return location
27 | }
28 |
29 | // String returns Timezone as string
30 | // Example: "Europe/Berlin"
31 | func (t Timezone) String() string {
32 | return string(t)
33 | }
34 |
--------------------------------------------------------------------------------
/timezone_constants.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | // All possible Timezones, which are supported by Go's "time" library
4 | const (
5 | AfricaAbidjan = Timezone("Africa/Abidjan")
6 | AfricaAccra = Timezone("Africa/Accra")
7 | AfricaAddisAbaba = Timezone("Africa/AddisAbaba")
8 | AfricaAlgiers = Timezone("Africa/Algiers")
9 | AfricaAsmara = Timezone("Africa/Asmara")
10 | AfricaBamako = Timezone("Africa/Bamako")
11 | AfricaBangui = Timezone("Africa/Bangui")
12 | AfricaBanjul = Timezone("Africa/Banjul")
13 | AfricaBissau = Timezone("Africa/Bissau")
14 | AfricaBlantyre = Timezone("Africa/Blantyre")
15 | AfricaBrazzaville = Timezone("Africa/Brazzaville")
16 | AfricaBujumbura = Timezone("Africa/Bujumbura")
17 | AfricaCairo = Timezone("Africa/Cairo")
18 | AfricaCasablanca = Timezone("Africa/Casablanca")
19 | AfricaCeuta = Timezone("Africa/Ceuta")
20 | AfricaConakry = Timezone("Africa/Conakry")
21 | AfricaDakar = Timezone("Africa/Dakar")
22 | AfricaDaresSalaam = Timezone("Africa/DaresSalaam")
23 | AfricaDjibouti = Timezone("Africa/Djibouti")
24 | AfricaDouala = Timezone("Africa/Douala")
25 | AfricaElAaiun = Timezone("Africa/ElAaiun")
26 | AfricaFreetown = Timezone("Africa/Freetown")
27 | AfricaGaborone = Timezone("Africa/Gaborone")
28 | AfricaHarare = Timezone("Africa/Harare")
29 | AfricaJohannesburg = Timezone("Africa/Johannesburg")
30 | AfricaJuba = Timezone("Africa/Juba")
31 | AfricaKampala = Timezone("Africa/Kampala")
32 | AfricaKhartoum = Timezone("Africa/Khartoum")
33 | AfricaKigali = Timezone("Africa/Kigali")
34 | AfricaKinshasa = Timezone("Africa/Kinshasa")
35 | AfricaLagos = Timezone("Africa/Lagos")
36 | AfricaLibreville = Timezone("Africa/Libreville")
37 | AfricaLome = Timezone("Africa/Lome")
38 | AfricaLuanda = Timezone("Africa/Luanda")
39 | AfricaLubumbashi = Timezone("Africa/Lubumbashi")
40 | AfricaLusaka = Timezone("Africa/Lusaka")
41 | AfricaMalabo = Timezone("Africa/Malabo")
42 | AfricaMaputo = Timezone("Africa/Maputo")
43 | AfricaMaseru = Timezone("Africa/Maseru")
44 | AfricaMbabane = Timezone("Africa/Mbabane")
45 | AfricaMogadishu = Timezone("Africa/Mogadishu")
46 | AfricaMonrovia = Timezone("Africa/Monrovia")
47 | AfricaNairobi = Timezone("Africa/Nairobi")
48 | AfricaNdjamena = Timezone("Africa/Ndjamena")
49 | AfricaNiamey = Timezone("Africa/Niamey")
50 | AfricaNouakchott = Timezone("Africa/Nouakchott")
51 | AfricaOuagadougou = Timezone("Africa/Ouagadougou")
52 | AfricaPortoNovo = Timezone("Africa/Porto-Novo")
53 | AfricaSaoTome = Timezone("Africa/SaoTome")
54 | AfricaTripoli = Timezone("Africa/Tripoli")
55 | AfricaTunis = Timezone("Africa/Tunis")
56 | AfricaWindhoek = Timezone("Africa/Windhoek")
57 | AmericaAdak = Timezone("America/Adak")
58 | AmericaAnchorage = Timezone("America/Anchorage")
59 | AmericaAnguilla = Timezone("America/Anguilla")
60 | AmericaAntigua = Timezone("America/Antigua")
61 | AmericaAraguaina = Timezone("America/Araguaina")
62 | AmericaArgentinaBuenosAires = Timezone("America/Argentina/BuenosAires")
63 | AmericaArgentinaCatamarca = Timezone("America/Argentina/Catamarca")
64 | AmericaArgentinaComodRivadavia = Timezone("America/Argentina/ComodRivadavia")
65 | AmericaArgentinaCordoba = Timezone("America/Argentina/Cordoba")
66 | AmericaArgentinaJujuy = Timezone("America/Argentina/Jujuy Jujuy")
67 | AmericaArgentinaLaRioja = Timezone("America/Argentina/LaRioja")
68 | AmericaArgentinaMendoza = Timezone("America/Argentina/Mendoza")
69 | AmericaArgentinaRioGallegos = Timezone("America/Argentina/RioGallegos")
70 | AmericaArgentinaSalta = Timezone("America/Argentina/Salta Salta")
71 | AmericaArgentinaSanJuan = Timezone("America/Argentina/SanJuan")
72 | AmericaArgentinaSanLuis = Timezone("America/Argentina/SanLuis")
73 | AmericaArgentinaTucuman = Timezone("America/Argentina/Tucuman")
74 | AmericaArgentinaUshuaia = Timezone("America/Argentina/Ushuaia")
75 | AmericaAruba = Timezone("America/Aruba")
76 | AmericaAsuncion = Timezone("America/Asuncion")
77 | AmericaAtikokan = Timezone("America/Atikokan")
78 | AmericaAtka = Timezone("America/Atka")
79 | AmericaBahia = Timezone("America/Bahia")
80 | AmericaBahiaBanderas = Timezone("America/BahiaBanderas")
81 | AmericaBarbados = Timezone("America/Barbados")
82 | AmericaBelem = Timezone("America/Belem")
83 | AmericaBelize = Timezone("America/Belize")
84 | AmericaBlanc = Timezone("America/Blanc")
85 | AmericaBoaVista = Timezone("America/BoaVista")
86 | AmericaBogota = Timezone("America/Bogota")
87 | AmericaBoise = Timezone("America/Boise")
88 | AmericaBuenosAires = Timezone("America/BuenosAires")
89 | AmericaCambridgeBay = Timezone("America/CambridgeBay")
90 | AmericaCampoGrande = Timezone("America/CampoGrande")
91 | AmericaCancun = Timezone("America/Cancun")
92 | AmericaCaracas = Timezone("America/Caracas")
93 | AmericaCatamarca = Timezone("America/Catamarca")
94 | AmericaCayenne = Timezone("America/Cayenne")
95 | AmericaCayman = Timezone("America/Cayman")
96 | AmericaChicago = Timezone("America/Chicago")
97 | AmericaChihuahua = Timezone("America/Chihuahua")
98 | AmericaCoralHarbour = Timezone("America/CoralHarbour")
99 | AmericaCordoba = Timezone("America/Cordoba")
100 | AmericaCostaRica = Timezone("America/CostaRica")
101 | AmericaCreston = Timezone("America/Creston")
102 | AmericaCuiaba = Timezone("America/Cuiaba")
103 | AmericaCuracao = Timezone("America/Curacao")
104 | AmericaDanmarkshavn = Timezone("America/Danmarkshavn")
105 | AmericaDawson = Timezone("America/Dawson")
106 | AmericaDawsonCreek = Timezone("America/DawsonCreek")
107 | AmericaDenver = Timezone("America/Denver")
108 | AmericaDetroit = Timezone("America/Detroit")
109 | AmericaDominica = Timezone("America/Dominica")
110 | AmericaEdmonton = Timezone("America/Edmonton")
111 | AmericaEirunepe = Timezone("America/Eirunepe")
112 | AmericaElSalvador = Timezone("America/ElSalvador")
113 | AmericaEnsenada = Timezone("America/Ensenada")
114 | AmericaFortNelson = Timezone("America/FortNelson")
115 | AmericaFortWayne = Timezone("America/FortWayne")
116 | AmericaFortaleza = Timezone("America/Fortaleza")
117 | AmericaGlaceBay = Timezone("America/GlaceBay")
118 | AmericaGodthab = Timezone("America/Godthab")
119 | AmericaGooseBay = Timezone("America/GooseBay")
120 | AmericaGrandTurk = Timezone("America/GrandTurk")
121 | AmericaGrenada = Timezone("America/Grenada")
122 | AmericaGuadeloupe = Timezone("America/Guadeloupe")
123 | AmericaGuatemala = Timezone("America/Guatemala")
124 | AmericaGuayaquil = Timezone("America/Guayaquil")
125 | AmericaGuyana = Timezone("America/Guyana")
126 | AmericaHalifax = Timezone("America/Halifax")
127 | AmericaHavana = Timezone("America/Havana")
128 | AmericaHermosillo = Timezone("America/Hermosillo")
129 | AmericaIndianaIndianapolis = Timezone("America/Indiana/Indianapolis")
130 | AmericaIndianaKnox = Timezone("America/Indiana/Knox")
131 | AmericaIndianaMarengo = Timezone("America/Indiana/Marengo")
132 | AmericaIndianaPetersburg = Timezone("America/Indiana/Petersburg")
133 | AmericaIndianaTellCity = Timezone("America/Indiana/TellCity")
134 | AmericaIndianaVevay = Timezone("America/Indiana/Vevay")
135 | AmericaIndianaVincennes = Timezone("America/Indiana/Vincennes")
136 | AmericaIndianaWinamac = Timezone("America/Indiana/Winamac")
137 | AmericaIndianapolis = Timezone("America/Indianapolis")
138 | AmericaInuvik = Timezone("America/Inuvik")
139 | AmericaIqaluit = Timezone("America/Iqaluit")
140 | AmericaJamaica = Timezone("America/Jamaica")
141 | AmericaJujuy = Timezone("America/Jujuy")
142 | AmericaJuneau = Timezone("America/Juneau")
143 | AmericaKentuckyLouisville = Timezone("America/Kentucky/Louisville")
144 | AmericaKentuckyMonticello = Timezone("America/Kentucky/Monticello")
145 | AmericaKnoxIN = Timezone("America/KnoxIN")
146 | AmericaKralendijk = Timezone("America/Kralendijk")
147 | AmericaLaPaz = Timezone("America/LaPaz")
148 | AmericaLima = Timezone("America/Lima")
149 | AmericaLosAngeles = Timezone("America/LosAngeles")
150 | AmericaLouisville = Timezone("America/Louisville")
151 | AmericaLowerPrinces = Timezone("America/LowerPrinces")
152 | AmericaMaceio = Timezone("America/Maceio")
153 | AmericaManagua = Timezone("America/Managua")
154 | AmericaManaus = Timezone("America/Manaus")
155 | AmericaMarigot = Timezone("America/Marigot")
156 | AmericaMartinique = Timezone("America/Martinique")
157 | AmericaMatamoros = Timezone("America/Matamoros")
158 | AmericaMazatlan = Timezone("America/Mazatlan")
159 | AmericaMendoza = Timezone("America/Mendoza")
160 | AmericaMenominee = Timezone("America/Menominee")
161 | AmericaMerida = Timezone("America/Merida")
162 | AmericaMetlakatla = Timezone("America/Metlakatla")
163 | AmericaMexicoCity = Timezone("America/MexicoCity")
164 | AmericaMiquelon = Timezone("America/Miquelon")
165 | AmericaMoncton = Timezone("America/Moncton")
166 | AmericaMonterrey = Timezone("America/Monterrey")
167 | AmericaMontevideo = Timezone("America/Montevideo")
168 | AmericaMontreal = Timezone("America/Montreal")
169 | AmericaMontserrat = Timezone("America/Montserrat")
170 | AmericaNassau = Timezone("America/Nassau")
171 | AmericaNewYork = Timezone("America/NewYork")
172 | AmericaNipigon = Timezone("America/Nipigon")
173 | AmericaNome = Timezone("America/Nome")
174 | AmericaNoronha = Timezone("America/Noronha")
175 | AmericaNorthDakotaBeulah = Timezone("America/NorthDakota/Beulah")
176 | AmericaNorthDakotaCenter = Timezone("America/NorthDakota/Center")
177 | AmericaNorthDakotaNewSalem = Timezone("America/NorthDakota/NewSalem")
178 | AmericaOjinaga = Timezone("America/Ojinaga")
179 | AmericaPanama = Timezone("America/Panama")
180 | AmericaPangnirtung = Timezone("America/Pangnirtung")
181 | AmericaParamaribo = Timezone("America/Paramaribo")
182 | AmericaPhoenix = Timezone("America/Phoenix")
183 | AmericaPortofSpain = Timezone("America/PortofSpain")
184 | AmericaPort = Timezone("America/Port")
185 | AmericaPortoAcre = Timezone("America/PortoAcre")
186 | AmericaPortoVelho = Timezone("America/PortoVelho")
187 | AmericaPuertoRico = Timezone("America/PuertoRico")
188 | AmericaPuntaArenas = Timezone("America/PuntaArenas")
189 | AmericaRainyRiver = Timezone("America/RainyRiver")
190 | AmericaRankinInlet = Timezone("America/RankinInlet")
191 | AmericaRecife = Timezone("America/Recife")
192 | AmericaRegina = Timezone("America/Regina")
193 | AmericaResolute = Timezone("America/Resolute")
194 | AmericaRioBranco = Timezone("America/RioBranco")
195 | AmericaRosario = Timezone("America/Rosario")
196 | AmericaSantaIsabel = Timezone("America/SantaIsabel")
197 | AmericaSantarem = Timezone("America/Santarem")
198 | AmericaSantiago = Timezone("America/Santiago")
199 | AmericaSantoDomingo = Timezone("America/SantoDomingo")
200 | AmericaSaoPaulo = Timezone("America/SaoPaulo")
201 | AmericaScoresbysund = Timezone("America/Scoresbysund")
202 | AmericaShiprock = Timezone("America/Shiprock")
203 | AmericaSitka = Timezone("America/Sitka")
204 | AmericaStBarthelemy = Timezone("America/StBarthelemy")
205 | AmericaStJohns = Timezone("America/StJohns")
206 | AmericaStKitts = Timezone("America/StKitts")
207 | AmericaStLucia = Timezone("America/StLucia")
208 | AmericaStThomas = Timezone("America/StThomas")
209 | AmericaStVincent = Timezone("America/StVincent")
210 | AmericaSwiftCurrent = Timezone("America/SwiftCurrent")
211 | AmericaTegucigalpa = Timezone("America/Tegucigalpa")
212 | AmericaThule = Timezone("America/Thule")
213 | AmericaThunderBay = Timezone("America/ThunderBay")
214 | AmericaTijuana = Timezone("America/Tijuana")
215 | AmericaToronto = Timezone("America/Toronto")
216 | AmericaTortola = Timezone("America/Tortola")
217 | AmericaVancouver = Timezone("America/Vancouver")
218 | AmericaVirgin = Timezone("America/Virgin")
219 | AmericaWhitehorse = Timezone("America/Whitehorse")
220 | AmericaWinnipeg = Timezone("America/Winnipeg")
221 | AmericaYakutat = Timezone("America/Yakutat")
222 | AmericaYellowknife = Timezone("America/Yellowknife")
223 | AntarcticaCasey = Timezone("Antarctica/Casey")
224 | AntarcticaDavis = Timezone("Antarctica/Davis")
225 | AntarcticaDumontDUrville = Timezone("Antarctica/DumontDUrville")
226 | AntarcticaMacquarie = Timezone("Antarctica/Macquarie")
227 | AntarcticaMawson = Timezone("Antarctica/Mawson")
228 | AntarcticaMcMurdo = Timezone("Antarctica/McMurdo")
229 | AntarcticaPalmer = Timezone("Antarctica/Palmer")
230 | AntarcticaRothera = Timezone("Antarctica/Rothera")
231 | AntarcticaSouthPole = Timezone("Antarctica/SouthPole")
232 | AntarcticaSyowa = Timezone("Antarctica/Syowa")
233 | AntarcticaTroll = Timezone("Antarctica/Troll")
234 | AntarcticaVostok = Timezone("Antarctica/Vostok")
235 | ArcticLongyearbyen = Timezone("Arctic/Longyearbyen")
236 | AsiaAden = Timezone("Asia/Aden")
237 | AsiaAlmaty = Timezone("Asia/Almaty")
238 | AsiaAmman = Timezone("Asia/Amman")
239 | AsiaAnadyr = Timezone("Asia/Anadyr")
240 | AsiaAqtau = Timezone("Asia/Aqtau")
241 | AsiaAqtobe = Timezone("Asia/Aqtobe")
242 | AsiaAshgabat = Timezone("Asia/Ashgabat")
243 | AsiaAshkhabad = Timezone("Asia/Ashkhabad")
244 | AsiaAtyrau = Timezone("Asia/Atyrau")
245 | AsiaBaghdad = Timezone("Asia/Baghdad")
246 | AsiaBahrain = Timezone("Asia/Bahrain")
247 | AsiaBaku = Timezone("Asia/Baku")
248 | AsiaBangkok = Timezone("Asia/Bangkok")
249 | AsiaBarnaul = Timezone("Asia/Barnaul")
250 | AsiaBeirut = Timezone("Asia/Beirut")
251 | AsiaBishkek = Timezone("Asia/Bishkek")
252 | AsiaBrunei = Timezone("Asia/Brunei")
253 | AsiaCalcutta = Timezone("Asia/Calcutta")
254 | AsiaChita = Timezone("Asia/Chita")
255 | AsiaChoibalsan = Timezone("Asia/Choibalsan")
256 | AsiaChongqing = Timezone("Asia/Chongqing")
257 | AsiaChungking = Timezone("Asia/Chungking")
258 | AsiaColombo = Timezone("Asia/Colombo")
259 | AsiaDacca = Timezone("Asia/Dacca")
260 | AsiaDamascus = Timezone("Asia/Damascus")
261 | AsiaDhaka = Timezone("Asia/Dhaka")
262 | AsiaDili = Timezone("Asia/Dili")
263 | AsiaDubai = Timezone("Asia/Dubai")
264 | AsiaDushanbe = Timezone("Asia/Dushanbe")
265 | AsiaFamagusta = Timezone("Asia/Famagusta")
266 | AsiaGaza = Timezone("Asia/Gaza")
267 | AsiaHarbin = Timezone("Asia/Harbin")
268 | AsiaHebron = Timezone("Asia/Hebron")
269 | AsiaHoChiMinh = Timezone("Asia/HoChiMinh")
270 | AsiaHongKong = Timezone("Asia/HongKong")
271 | AsiaHovd = Timezone("Asia/Hovd")
272 | AsiaIrkutsk = Timezone("Asia/Irkutsk")
273 | AsiaIstanbul = Timezone("Asia/Istanbul")
274 | AsiaJakarta = Timezone("Asia/Jakarta")
275 | AsiaJayapura = Timezone("Asia/Jayapura")
276 | AsiaJerusalem = Timezone("Asia/Jerusalem")
277 | AsiaKabul = Timezone("Asia/Kabul")
278 | AsiaKamchatka = Timezone("Asia/Kamchatka")
279 | AsiaKarachi = Timezone("Asia/Karachi")
280 | AsiaKashgar = Timezone("Asia/Kashgar")
281 | AsiaKathmandu = Timezone("Asia/Kathmandu")
282 | AsiaKatmandu = Timezone("Asia/Katmandu")
283 | AsiaKhandyga = Timezone("Asia/Khandyga")
284 | AsiaKolkata = Timezone("Asia/Kolkata")
285 | AsiaKrasnoyarsk = Timezone("Asia/Krasnoyarsk")
286 | AsiaKualaLumpur = Timezone("Asia/KualaLumpur")
287 | AsiaKuching = Timezone("Asia/Kuching")
288 | AsiaKuwait = Timezone("Asia/Kuwait")
289 | AsiaMacao = Timezone("Asia/Macao")
290 | AsiaMacau = Timezone("Asia/Macau")
291 | AsiaMagadan = Timezone("Asia/Magadan")
292 | AsiaMakassar = Timezone("Asia/Makassar")
293 | AsiaManila = Timezone("Asia/Manila")
294 | AsiaMuscat = Timezone("Asia/Muscat")
295 | AsiaNovokuznetsk = Timezone("Asia/Novokuznetsk")
296 | AsiaNovosibirsk = Timezone("Asia/Novosibirsk")
297 | AsiaOmsk = Timezone("Asia/Omsk")
298 | AsiaOral = Timezone("Asia/Oral")
299 | AsiaPhnomPenh = Timezone("Asia/PhnomPenh")
300 | AsiaPontianak = Timezone("Asia/Pontianak")
301 | AsiaPyongyang = Timezone("Asia/Pyongyang")
302 | AsiaQatar = Timezone("Asia/Qatar")
303 | AsiaQyzylorda = Timezone("Asia/Qyzylorda")
304 | AsiaRangoon = Timezone("Asia/Rangoon")
305 | AsiaRiyadh = Timezone("Asia/Riyadh")
306 | AsiaSaigon = Timezone("Asia/Saigon")
307 | AsiaSakhalin = Timezone("Asia/Sakhalin")
308 | AsiaSamarkand = Timezone("Asia/Samarkand")
309 | AsiaSeoul = Timezone("Asia/Seoul")
310 | AsiaShanghai = Timezone("Asia/Shanghai")
311 | AsiaSingapore = Timezone("Asia/Singapore")
312 | AsiaSrednekolymsk = Timezone("Asia/Srednekolymsk")
313 | AsiaTaipei = Timezone("Asia/Taipei")
314 | AsiaTashkent = Timezone("Asia/Tashkent")
315 | AsiaTbilisi = Timezone("Asia/Tbilisi")
316 | AsiaTehran = Timezone("Asia/Tehran")
317 | AsiaTelAviv = Timezone("Asia/TelAviv")
318 | AsiaThimbu = Timezone("Asia/Thimbu")
319 | AsiaThimphu = Timezone("Asia/Thimphu")
320 | AsiaTokyo = Timezone("Asia/Tokyo")
321 | AsiaTomsk = Timezone("Asia/Tomsk")
322 | AsiaUjungPandang = Timezone("Asia/UjungPandang")
323 | AsiaUlaanbaatar = Timezone("Asia/Ulaanbaatar")
324 | AsiaUlanBator = Timezone("Asia/UlanBator")
325 | AsiaUrumqi = Timezone("Asia/Urumqi")
326 | AsiaUst = Timezone("Asia/Ust")
327 | AsiaVientiane = Timezone("Asia/Vientiane")
328 | AsiaVladivostok = Timezone("Asia/Vladivostok")
329 | AsiaYakutsk = Timezone("Asia/Yakutsk")
330 | AsiaYangon = Timezone("Asia/Yangon")
331 | AsiaYekaterinburg = Timezone("Asia/Yekaterinburg")
332 | AsiaYerevan = Timezone("Asia/Yerevan")
333 | AtlanticAzores = Timezone("Atlantic/Azores")
334 | AtlanticBermuda = Timezone("Atlantic/Bermuda")
335 | AtlanticCanary = Timezone("Atlantic/Canary")
336 | AtlanticCapeVerde = Timezone("Atlantic/CapeVerde")
337 | AtlanticFaeroe = Timezone("Atlantic/Faeroe")
338 | AtlanticFaroe = Timezone("Atlantic/Faroe")
339 | AtlanticJanMayen = Timezone("Atlantic/JanMayen")
340 | AtlanticMadeira = Timezone("Atlantic/Madeira")
341 | AtlanticReykjavik = Timezone("Atlantic/Reykjavik")
342 | AtlanticSouthGeorgia = Timezone("Atlantic/SouthGeorgia")
343 | AtlanticStHelena = Timezone("Atlantic/StHelena")
344 | AtlanticStanley = Timezone("Atlantic/Stanley")
345 | AustraliaACT = Timezone("Australia/ACT")
346 | AustraliaAdelaide = Timezone("Australia/Adelaide")
347 | AustraliaBrisbane = Timezone("Australia/Brisbane")
348 | AustraliaBrokenHill = Timezone("Australia/BrokenHill")
349 | AustraliaCanberra = Timezone("Australia/Canberra")
350 | AustraliaCurrie = Timezone("Australia/Currie")
351 | AustraliaDarwin = Timezone("Australia/Darwin")
352 | AustraliaEucla = Timezone("Australia/Eucla")
353 | AustraliaHobart = Timezone("Australia/Hobart")
354 | AustraliaLHI = Timezone("Australia/LHI")
355 | AustraliaLindeman = Timezone("Australia/Lindeman")
356 | AustraliaLordHowe = Timezone("Australia/LordHowe")
357 | AustraliaMelbourne = Timezone("Australia/Melbourne")
358 | AustraliaNorth = Timezone("Australia/North")
359 | AustraliaNSW = Timezone("Australia/NSW")
360 | AustraliaPerth = Timezone("Australia/Perth")
361 | AustraliaQueensland = Timezone("Australia/Queensland")
362 | AustraliaSouth = Timezone("Australia/South")
363 | AustraliaSydney = Timezone("Australia/Sydney")
364 | AustraliaTasmania = Timezone("Australia/Tasmania")
365 | AustraliaVictoria = Timezone("Australia/Victoria")
366 | AustraliaWest = Timezone("Australia/West")
367 | AustraliaYancowinna = Timezone("Australia/Yancowinna")
368 | BrazilAcre = Timezone("Brazil/Acre")
369 | BrazilDeNoronha = Timezone("Brazil/DeNoronha")
370 | BrazilEast = Timezone("Brazil/East")
371 | BrazilWest = Timezone("Brazil/West")
372 | CanadaAtlantic = Timezone("Canada/Atlantic")
373 | CanadaCentral = Timezone("Canada/Central")
374 | CanadaEastern = Timezone("Canada/Eastern")
375 | CanadaMountain = Timezone("Canada/Mountain")
376 | CanadaNewfoundland = Timezone("Canada/Newfoundland")
377 | CanadaPacific = Timezone("Canada/Pacific")
378 | CanadaSaskatchewan = Timezone("Canada/Saskatchewan")
379 | CanadaYukon = Timezone("Canada/Yukon")
380 | CET = Timezone("CET")
381 | ChileContinental = Timezone("Chile/Continental")
382 | ChileEasterIsland = Timezone("Chile/EasterIsland")
383 | CST6CDT = Timezone("CST6CDT")
384 | Cuba = Timezone("Cuba")
385 | EET = Timezone("EET")
386 | Egypt = Timezone("Egypt")
387 | Eire = Timezone("Eire")
388 | EST = Timezone("EST")
389 | EST5EDT = Timezone("EST5EDT")
390 | EtcGMT = Timezone("Etc/GMT")
391 | EtcGMTPlus0 = Timezone("Etc/GMT+0")
392 | EtcGMTPlus1 = Timezone("Etc/GMT+1")
393 | EtcGMTPlus10 = Timezone("Etc/GMT+10")
394 | EtcGMTPlus11 = Timezone("Etc/GMT+11")
395 | EtcGMTPlus12 = Timezone("Etc/GMT+12")
396 | EtcGMTPlus2 = Timezone("Etc/GMT+2")
397 | EtcGMTPlus3 = Timezone("Etc/GMT+3")
398 | EtcGMTPlus4 = Timezone("Etc/GMT+4")
399 | EtcGMTPlus5 = Timezone("Etc/GMT+5")
400 | EtcGMTPlus6 = Timezone("Etc/GMT+6")
401 | EtcGMTPlus7 = Timezone("Etc/GMT+7")
402 | EtcGMTPlus8 = Timezone("Etc/GMT+8")
403 | EtcGMTPlus9 = Timezone("Etc/GMT+9")
404 | EtcGMT0 = Timezone("Etc/GMT0")
405 | EtcGMTMinus0 = Timezone("Etc/GMT-0")
406 | EtcGMTMinus1 = Timezone("Etc/GMT-1")
407 | EtcGMTMinus10 = Timezone("Etc/GMT-10")
408 | EtcGMTMinus11 = Timezone("Etc/GMT-11")
409 | EtcGMTMinus12 = Timezone("Etc/GMT-12")
410 | EtcGMTMinus13 = Timezone("Etc/GMT-13")
411 | EtcGMTMinus14 = Timezone("Etc/GMT-14")
412 | EtcGMTMinus2 = Timezone("Etc/GMT-2")
413 | EtcGMTMinus3 = Timezone("Etc/GMT-3")
414 | EtcGMTMinus4 = Timezone("Etc/GMT-4")
415 | EtcGMTMinus5 = Timezone("Etc/GMT-5")
416 | EtcGMTMinus6 = Timezone("Etc/GMT-6")
417 | EtcGMTMinus7 = Timezone("Etc/GMT-7")
418 | EtcGMTMinus8 = Timezone("Etc/GMT-8")
419 | EtcGMTMinus9 = Timezone("Etc/GMT-9")
420 | EtcGreenwich = Timezone("Etc/Greenwich")
421 | EtcUCT = Timezone("Etc/UCT")
422 | EtcUniversal = Timezone("Etc/Universal")
423 | EtcUTC = Timezone("Etc/UTC")
424 | EtcZulu = Timezone("Etc/Zulu")
425 | EuropeAmsterdam = Timezone("Europe/Amsterdam")
426 | EuropeAndorra = Timezone("Europe/Andorra")
427 | EuropeAstrakhan = Timezone("Europe/Astrakhan")
428 | EuropeAthens = Timezone("Europe/Athens")
429 | EuropeBelfast = Timezone("Europe/Belfast")
430 | EuropeBelgrade = Timezone("Europe/Belgrade")
431 | EuropeBerlin = Timezone("Europe/Berlin")
432 | EuropeBratislava = Timezone("Europe/Bratislava")
433 | EuropeBrussels = Timezone("Europe/Brussels")
434 | EuropeBucharest = Timezone("Europe/Bucharest")
435 | EuropeBudapest = Timezone("Europe/Budapest")
436 | EuropeBusingen = Timezone("Europe/Busingen")
437 | EuropeChisinau = Timezone("Europe/Chisinau")
438 | EuropeCopenhagen = Timezone("Europe/Copenhagen")
439 | EuropeDublin = Timezone("Europe/Dublin")
440 | EuropeGibraltar = Timezone("Europe/Gibraltar")
441 | EuropeGuernsey = Timezone("Europe/Guernsey")
442 | EuropeHelsinki = Timezone("Europe/Helsinki")
443 | EuropeIsleofMan = Timezone("Europe/IsleofMan")
444 | EuropeIstanbul = Timezone("Europe/Istanbul")
445 | EuropeJersey = Timezone("Europe/Jersey")
446 | EuropeKaliningrad = Timezone("Europe/Kaliningrad")
447 | EuropeKiev = Timezone("Europe/Kiev")
448 | EuropeKirov = Timezone("Europe/Kirov")
449 | EuropeLisbon = Timezone("Europe/Lisbon")
450 | EuropeLjubljana = Timezone("Europe/Ljubljana")
451 | EuropeLondon = Timezone("Europe/London")
452 | EuropeLuxembourg = Timezone("Europe/Luxembourg")
453 | EuropeMadrid = Timezone("Europe/Madrid")
454 | EuropeMalta = Timezone("Europe/Malta")
455 | EuropeMariehamn = Timezone("Europe/Mariehamn")
456 | EuropeMinsk = Timezone("Europe/Minsk")
457 | EuropeMonaco = Timezone("Europe/Monaco")
458 | EuropeMoscow = Timezone("Europe/Moscow")
459 | AsiaNicosia = Timezone("Asia/Nicosia")
460 | EuropeOslo = Timezone("Europe/Oslo")
461 | EuropeParis = Timezone("Europe/Paris")
462 | EuropePodgorica = Timezone("Europe/Podgorica")
463 | EuropePrague = Timezone("Europe/Prague")
464 | EuropeRiga = Timezone("Europe/Riga")
465 | EuropeRome = Timezone("Europe/Rome")
466 | EuropeSamara = Timezone("Europe/Samara")
467 | EuropeSanMarino = Timezone("Europe/SanMarino")
468 | EuropeSarajevo = Timezone("Europe/Sarajevo")
469 | EuropeSaratov = Timezone("Europe/Saratov")
470 | EuropeSimferopol = Timezone("Europe/Simferopol")
471 | EuropeSkopje = Timezone("Europe/Skopje")
472 | EuropeSofia = Timezone("Europe/Sofia")
473 | EuropeStockholm = Timezone("Europe/Stockholm")
474 | EuropeTallinn = Timezone("Europe/Tallinn")
475 | EuropeTirane = Timezone("Europe/Tirane")
476 | EuropeTiraspol = Timezone("Europe/Tiraspol")
477 | EuropeUlyanovsk = Timezone("Europe/Ulyanovsk")
478 | EuropeUzhgorod = Timezone("Europe/Uzhgorod")
479 | EuropeVaduz = Timezone("Europe/Vaduz")
480 | EuropeVatican = Timezone("Europe/Vatican")
481 | EuropeVienna = Timezone("Europe/Vienna")
482 | EuropeVilnius = Timezone("Europe/Vilnius")
483 | EuropeVolgograd = Timezone("Europe/Volgograd")
484 | EuropeWarsaw = Timezone("Europe/Warsaw")
485 | EuropeZagreb = Timezone("Europe/Zagreb")
486 | EuropeZaporozhye = Timezone("Europe/Zaporozhye")
487 | EuropeZurich = Timezone("Europe/Zurich")
488 | GB = Timezone("GB")
489 | GBEire = Timezone("GB-Eire")
490 | GMT = Timezone("GMT")
491 | GMTPlus0 = Timezone("GMT+0")
492 | GMT0 = Timezone("GMT0")
493 | GMTMinus0 = Timezone("GMT-0")
494 | Greenwich = Timezone("Greenwich")
495 | Hongkong = Timezone("Hongkong")
496 | HST = Timezone("HST")
497 | Iceland = Timezone("Iceland")
498 | IndianAntananarivo = Timezone("Indian/Antananarivo")
499 | IndianChagos = Timezone("Indian/Chagos")
500 | IndianChristmas = Timezone("Indian/Christmas")
501 | IndianCocos = Timezone("Indian/Cocos")
502 | IndianComoro = Timezone("Indian/Comoro")
503 | IndianKerguelen = Timezone("Indian/Kerguelen")
504 | IndianMahe = Timezone("Indian/Mahe")
505 | IndianMaldives = Timezone("Indian/Maldives")
506 | IndianMauritius = Timezone("Indian/Mauritius")
507 | IndianMayotte = Timezone("Indian/Mayotte")
508 | IndianReunion = Timezone("Indian/Reunion")
509 | Iran = Timezone("Iran")
510 | Israel = Timezone("Israel")
511 | Jamaica = Timezone("Jamaica")
512 | Japan = Timezone("Japan")
513 | Kwajalein = Timezone("Kwajalein")
514 | Libya = Timezone("Libya")
515 | MET = Timezone("MET")
516 | MexicoBajaNorte = Timezone("Mexico/BajaNorte")
517 | MexicoBajaSur = Timezone("Mexico/BajaSur")
518 | MexicoGeneral = Timezone("Mexico/General")
519 | MST = Timezone("MST")
520 | MST7MDT = Timezone("MST7MDT")
521 | Navajo = Timezone("Navajo")
522 | NZ = Timezone("NZ")
523 | NZCHAT = Timezone("NZ-CHAT")
524 | PacificApia = Timezone("Pacific/Apia")
525 | PacificAuckland = Timezone("Pacific/Auckland")
526 | PacificBougainville = Timezone("Pacific/Bougainville")
527 | PacificChatham = Timezone("Pacific/Chatham")
528 | PacificChuuk = Timezone("Pacific/Chuuk")
529 | PacificEaster = Timezone("Pacific/Easter")
530 | PacificEfate = Timezone("Pacific/Efate")
531 | PacificEnderbury = Timezone("Pacific/Enderbury")
532 | PacificFakaofo = Timezone("Pacific/Fakaofo")
533 | PacificFiji = Timezone("Pacific/Fiji")
534 | PacificFunafuti = Timezone("Pacific/Funafuti")
535 | PacificGalapagos = Timezone("Pacific/Galapagos")
536 | PacificGambier = Timezone("Pacific/Gambier")
537 | PacificGuadalcanal = Timezone("Pacific/Guadalcanal")
538 | PacificGuam = Timezone("Pacific/Guam")
539 | PacificHonolulu = Timezone("Pacific/Honolulu")
540 | PacificJohnston = Timezone("Pacific/Johnston")
541 | PacificKiritimati = Timezone("Pacific/Kiritimati")
542 | PacificKosrae = Timezone("Pacific/Kosrae")
543 | PacificKwajalein = Timezone("Pacific/Kwajalein")
544 | PacificMajuro = Timezone("Pacific/Majuro")
545 | PacificMarquesas = Timezone("Pacific/Marquesas")
546 | PacificMidway = Timezone("Pacific/Midway")
547 | PacificNauru = Timezone("Pacific/Nauru")
548 | PacificNiue = Timezone("Pacific/Niue")
549 | PacificNorfolk = Timezone("Pacific/Norfolk")
550 | PacificNoumea = Timezone("Pacific/Noumea")
551 | PacificPagoPago = Timezone("Pacific/PagoPago")
552 | PacificPalau = Timezone("Pacific/Palau")
553 | PacificPitcairn = Timezone("Pacific/Pitcairn")
554 | PacificPohnpei = Timezone("Pacific/Pohnpei")
555 | PacificPonape = Timezone("Pacific/Ponape")
556 | PacificPortMoresby = Timezone("Pacific/PortMoresby")
557 | PacificRarotonga = Timezone("Pacific/Rarotonga")
558 | PacificSaipan = Timezone("Pacific/Saipan")
559 | PacificSamoa = Timezone("Pacific/Samoa")
560 | PacificTahiti = Timezone("Pacific/Tahiti")
561 | PacificTarawa = Timezone("Pacific/Tarawa")
562 | PacificTongatapu = Timezone("Pacific/Tongatapu")
563 | PacificTruk = Timezone("Pacific/Truk")
564 | PacificWake = Timezone("Pacific/Wake")
565 | PacificWallis = Timezone("Pacific/Wallis")
566 | PacificYap = Timezone("Pacific/Yap")
567 | Poland = Timezone("Poland")
568 | Portugal = Timezone("Portugal")
569 | PRC = Timezone("PRC")
570 | PST8PDT = Timezone("PST8PDT")
571 | ROC = Timezone("ROC")
572 | ROK = Timezone("ROK")
573 | Singapore = Timezone("Singapore")
574 | Turkey = Timezone("Turkey")
575 | UCT = Timezone("UCT")
576 | Universal = Timezone("Universal")
577 | USAlaska = Timezone("US/Alaska")
578 | USAleutian = Timezone("US/Aleutian")
579 | USArizona = Timezone("US/Arizona")
580 | USCentral = Timezone("US/Central")
581 | USEastern = Timezone("US/Eastern")
582 | USEastIndiana = Timezone("US/East-Indiana")
583 | USHawaii = Timezone("US/Hawaii")
584 | USIndianaStarke = Timezone("US/Indiana-Starke")
585 | USMichigan = Timezone("US/Michigan")
586 | USMountain = Timezone("US/Mountain")
587 | USPacific = Timezone("US/Pacific")
588 | USPacificNew = Timezone("US/Pacific-New")
589 | USSamoa = Timezone("US/Samoa")
590 | UTC = Timezone("UTC")
591 | WET = Timezone("WET")
592 | WSU = Timezone("W-SU")
593 | Zulu = Timezone("Zulu")
594 | )
595 |
--------------------------------------------------------------------------------
/timezone_test.go:
--------------------------------------------------------------------------------
1 | package gostradamus
2 |
3 | import (
4 | "github.com/stretchr/testify/assert"
5 | "testing"
6 | )
7 |
8 | func TestTimezone_Location(t *testing.T) {
9 | actual := Timezone("notexist")
10 | assert.PanicsWithError(
11 | t,
12 | "unknown time zone notexist",
13 | func() {
14 | actual.Location()
15 | },
16 | )
17 | }
18 |
--------------------------------------------------------------------------------