From 07c74683b255cc1eb73db5c760f13d6c8b34d044 Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Mon, 13 Nov 2023 01:04:08 +0900 Subject: [PATCH 1/4] use timefmt-go library and implement Strftime method --- go.mod | 2 ++ go.sum | 2 ++ time.go | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ time_test.go | 9 +++++ 4 files changed, 113 insertions(+) diff --git a/go.mod b/go.mod index fbcb272..d9abc5d 100644 --- a/go.mod +++ b/go.mod @@ -3,3 +3,5 @@ module github.com/Code-Hex/synchro go 1.20.0 require github.com/google/go-cmp v0.5.9 + +require github.com/itchyny/timefmt-go v0.1.5 diff --git a/go.sum b/go.sum index 62841cd..29f8b12 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,4 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= +github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= diff --git a/time.go b/time.go index 31815b3..6872bd0 100644 --- a/time.go +++ b/time.go @@ -3,6 +3,8 @@ package synchro import ( "math" "time" + + "github.com/itchyny/timefmt-go" ) type empty[T TimeZone] struct{} @@ -108,3 +110,101 @@ func (t Time[T]) DiffInCalendarDays(u Time[T]) int { u1 := u.Truncate(day) return int(math.Ceil(float64(t1.Sub(u1)) / float64(day))) } + +// Strftime formats the time according to the given format string. +// +// This method is a wrapper for the [github.com/itchyny/timefmt-go] library. +// +// Example: +// - %Y-%m-%d %H:%M:%S => 2023-09-02 14:09:56 +// - %a, %d %b %Y %T %z => Sat, 02 Sep 2023 14:09:56 +0900 +// +// The format string should follow the format of [strftime(3)] in man pages. +// The following table shows the supported format specifiers: +// +// %a: +// Abbreviated weekday name (Sun) +// %A: +// Full weekday name (Sunday) +// %b: +// Abbreviated month name (Jan) +// %B: +// Full month name (January) +// %c: +// Date and time representation +// %C: +// Year divided by 100 (00-99) +// %d: +// Day of the month (01-31) +// %D: +// Short MM/DD/YY date, equivalent to %m/%d/%y +// %e: +// Day of the month, with a space preceding single digits ( 1-31) +// %F: +// Equivalent to %Y-%m-%d (the ISO 8601 date format) +// %g: +// Week-based year, last two digits (00-99) +// %G: +// Week-based year +// %h: +// Abbreviated month name (Jan) +// %H: +// Hour in 24h format (00-23) +// %I: +// Hour in 12h format (01-12) +// %j: +// Day of the year (001-366) +// %m: +// Month as a decimal number (01-12) +// %M: +// Minute (00-59) +// %n: +// New-line character +// %p: +// AM or PM designation +// %P: +// am or pm designation +// %r: +// 12-hour clock time +// %R: +// 24-hour HH:MM time, equivalent to %H:%M +// %S: +// Second (00-59) +// %t: +// Horizontal-tab character +// %T: +// 24-hour clock time, equivalent to %H:%M:%S +// %u: +// ISO 8601 weekday as number with Monday as 1 (1-7) +// %U: +// Week number with the first Sunday as the first day of week (00-53) +// %V: +// ISO 8601 week number (01-53) +// %w: +// Weekday as a decimal number with Sunday as 0 (0-6) +// %W: +// Week number with the first Monday as the first day of week (00-53) +// %x: +// Date representation +// %X: +// Time representation +// %y: +// Year, last two digits (00-99) +// %Y: +// Year +// %z: +// ISO 8601 offset from UTC in timezone (+HHMM) +// %Z: +// Timezone name or abbreviation +// %+: +// Extended date and time representation +// %::z: +// Colon-separated offset from UTC in timezone (e.g. +05:00) +// %:::z: +// Like %::z, but with optional seconds +// +// [strftime(3)]: https://linux.die.net/man/3/strftime +// [github.com/itchyny/timefmt-go]: https://github.com/itchyny/timefmt-go +func (t Time[T]) Strftime(format string) string { + return timefmt.Format(t.StdTime(), format) +} diff --git a/time_test.go b/time_test.go index 96f7fef..a2a31e6 100644 --- a/time_test.go +++ b/time_test.go @@ -614,3 +614,12 @@ func TestDiffInCalendarDays(t *testing.T) { }) } } + +func ExampleTime_Strftime() { + t := synchro.New[tz.AsiaTokyo](2023, 9, 2, 14, 9, 56, 0) + fmt.Println(t.Strftime("%Y-%m-%d %H:%M:%S")) + fmt.Println(t.Strftime("%a, %d %b %Y %T %z")) + // Output: + // 2023-09-02 14:09:56 + // Sat, 02 Sep 2023 14:09:56 +0900 +} From 1ed42c6d6f061dc659cb050ec247c2a084e1f8c3 Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Mon, 13 Nov 2023 01:05:27 +0900 Subject: [PATCH 2/4] updated README for Strftime method --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 96737fb..78ee23b 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ If you have a feature request, please open an issue. It would be great if you co - [In](https://pkg.go.dev/github.com/Code-Hex/synchro#In) - [ConvertTz](https://pkg.go.dev/github.com/Code-Hex/synchro#ConvertTz) +- [Strftime](https://pkg.go.dev/github.com/Code-Hex/synchro#Strftime) - [NowContext](https://pkg.go.dev/github.com/Code-Hex/synchro#NowContext) - [Quarter](https://pkg.go.dev/github.com/Code-Hex/synchro#Quarter) - [Semester](https://pkg.go.dev/github.com/Code-Hex/synchro#Semester) From 3317ee609e279596d1c272f2e6510bb1af6a3e4b Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Mon, 13 Nov 2023 01:28:47 +0900 Subject: [PATCH 3/4] added Strptime function --- time.go | 178 +++++++++++++++++++++++++++------------------------ time_test.go | 11 ++++ 2 files changed, 107 insertions(+), 82 deletions(-) diff --git a/time.go b/time.go index 6872bd0..d36105d 100644 --- a/time.go +++ b/time.go @@ -120,91 +120,105 @@ func (t Time[T]) DiffInCalendarDays(u Time[T]) int { // - %a, %d %b %Y %T %z => Sat, 02 Sep 2023 14:09:56 +0900 // // The format string should follow the format of [strftime(3)] in man pages. -// The following table shows the supported format specifiers: -// -// %a: -// Abbreviated weekday name (Sun) -// %A: -// Full weekday name (Sunday) -// %b: -// Abbreviated month name (Jan) -// %B: -// Full month name (January) -// %c: -// Date and time representation -// %C: -// Year divided by 100 (00-99) -// %d: -// Day of the month (01-31) -// %D: -// Short MM/DD/YY date, equivalent to %m/%d/%y -// %e: -// Day of the month, with a space preceding single digits ( 1-31) -// %F: -// Equivalent to %Y-%m-%d (the ISO 8601 date format) -// %g: -// Week-based year, last two digits (00-99) -// %G: -// Week-based year -// %h: -// Abbreviated month name (Jan) -// %H: -// Hour in 24h format (00-23) -// %I: -// Hour in 12h format (01-12) -// %j: -// Day of the year (001-366) -// %m: -// Month as a decimal number (01-12) -// %M: -// Minute (00-59) -// %n: -// New-line character -// %p: -// AM or PM designation -// %P: -// am or pm designation -// %r: -// 12-hour clock time -// %R: -// 24-hour HH:MM time, equivalent to %H:%M -// %S: -// Second (00-59) -// %t: -// Horizontal-tab character -// %T: -// 24-hour clock time, equivalent to %H:%M:%S -// %u: -// ISO 8601 weekday as number with Monday as 1 (1-7) -// %U: -// Week number with the first Sunday as the first day of week (00-53) -// %V: -// ISO 8601 week number (01-53) -// %w: -// Weekday as a decimal number with Sunday as 0 (0-6) -// %W: -// Week number with the first Monday as the first day of week (00-53) -// %x: -// Date representation -// %X: -// Time representation -// %y: -// Year, last two digits (00-99) -// %Y: -// Year -// %z: -// ISO 8601 offset from UTC in timezone (+HHMM) -// %Z: -// Timezone name or abbreviation -// %+: -// Extended date and time representation -// %::z: -// Colon-separated offset from UTC in timezone (e.g. +05:00) -// %:::z: -// Like %::z, but with optional seconds +// The following list shows the supported format specifiers: +// - %a: Abbreviated weekday name (Sun) +// - %A: Full weekday name (Sunday) +// - %b: Abbreviated month name (Jan) +// - %B: Full month name (January) +// - %c: Date and time representation +// - %C: Year divided by 100 (00-99) +// - %d: Day of the month (01-31) +// - %D: Short MM/DD/YY date, equivalent to %m/%d/%y +// - %e: Day of the month, with a space preceding single digits ( 1-31) +// - %F: Equivalent to %Y-%m-%d (the ISO 8601 date format) +// - %g: Week-based year, last two digits (00-99) +// - %G: Week-based year +// - %h: Abbreviated month name (Jan) +// - %H: Hour in 24h format (00-23) +// - %I: Hour in 12h format (01-12) +// - %j: Day of the year (001-366) +// - %m: Month as a decimal number (01-12) +// - %M: Minute (00-59) +// - %n: New-line character +// - %p: AM or PM designation +// - %P: am or pm designation +// - %r: 12-hour clock time +// - %R: 24-hour HH:MM time, equivalent to %H:%M +// - %S: Second (00-59) +// - %t: Horizontal-tab character +// - %T: 24-hour clock time, equivalent to %H:%M:%S +// - %u: ISO 8601 weekday as number with Monday as 1 (1-7) +// - %U: Week number with the first Sunday as the first day of week (00-53) +// - %V: ISO 8601 week number (01-53) +// - %w: Weekday as a decimal number with Sunday as 0 (0-6) +// - %W: Week number with the first Monday as the first day of week (00-53) +// - %x: Date representation +// - %X: Time representation +// - %y: Year, last two digits (00-99) +// - %Y: Year +// - %z: ISO 8601 offset from UTC in timezone (+HHMM) +// - %Z: Timezone name or abbreviation +// - %+: Extended date and time representation +// - %::z: Colon-separated offset from UTC in timezone (e.g. +05:00) +// - %:::z: Like %::z, but with optional seconds // // [strftime(3)]: https://linux.die.net/man/3/strftime // [github.com/itchyny/timefmt-go]: https://github.com/itchyny/timefmt-go func (t Time[T]) Strftime(format string) string { return timefmt.Format(t.StdTime(), format) } + +// Strptime parses time string with the default location. +// The location is also used to parse the time zone name (%Z). +// +// The format string should follow the format of [strptime(3)] in man pages. +// The following list shows the supported format specifiers: +// - %a: abbreviated weekday name +// - %A: full weekday name +// - %b: abbreviated month name +// - %B: full month name +// - %c: preferred date and time representation +// - %C: century number (00-99) +// - %d: day of the month (01-31) +// - %D: same as %m/%d/%y +// - %e: day of the month (1-31) +// - %F: same as %Y-%m-%d +// - %g: last two digits of the year (00-99) +// - %G: year as a 4-digit number +// - %h: same as %b +// - %H: hour (00-23) +// - %I: hour (01-12) +// - %j: day of the year (001-366) +// - %m: month (01-12) +// - %M: minute (00-59) +// - %n: newline character +// - %p: either "am" or "pm" according to the given time value +// - %r: time in a.m. and p.m. notation +// - %R: time in 24 hour notation +// - %S: second (00-60) +// - %t: tab character +// - %T: current time, equal to %H:%M:%S +// - %u: weekday as a number (1-7) +// - %U: week number of the current year, starting with the first Sunday as the first day of the first week +// - %V: week number of the current year, starting with the first week that has at least 4 days in the new year +// - %w: day of the week as a decimal, Sunday being 0 +// - %W: week number of the current year, starting with the first Monday as the first day of the first week +// - %x: preferred date representation without the time +// - %X: preferred time representation without the date +// - %y: year without a century (00-99) +// - %Y: year with century +// - %z: time zone offset, such as "-0700" +// - %Z: time zone name, such as "UTC" or "GMT" +// +// This is a wrapper for the [github.com/itchyny/timefmt-go] library. +// +// [strptime(3)]: https://linux.die.net/man/3/strptime +// [github.com/itchyny/timefmt-go]: https://github.com/itchyny/timefmt-go +func Strptime[T TimeZone](source string, format string) (Time[T], error) { + var tz T + tm, err := timefmt.ParseInLocation(source, format, tz.Location()) + if err != nil { + return Time[T]{}, err + } + return In[T](tm), nil +} diff --git a/time_test.go b/time_test.go index a2a31e6..c1aa9e8 100644 --- a/time_test.go +++ b/time_test.go @@ -623,3 +623,14 @@ func ExampleTime_Strftime() { // 2023-09-02 14:09:56 // Sat, 02 Sep 2023 14:09:56 +0900 } + +func ExampleStrptime() { + t, _ := synchro.Strptime[tz.AsiaTokyo]("2023-09-02 14:09:56", "%Y-%m-%d %H:%M:%S") + fmt.Println(t) + + _, err := synchro.Strptime[tz.UTC]("invalid", "%Y") + fmt.Println("error", err) // Returns an error as the layout is not a valid time value + // Output: + // 2023-09-02 14:09:56 +0900 JST + // error failed to parse "invalid" with "%Y": cannot parse %Y +} From 75dcef1087b03c4ac5d38ae0502eef5bf0818507 Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Mon, 13 Nov 2023 01:29:04 +0900 Subject: [PATCH 4/4] updated README for Strptime function --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 78ee23b..5efc69c 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,6 @@ If you have a feature request, please open an issue. It would be great if you co - [In](https://pkg.go.dev/github.com/Code-Hex/synchro#In) - [ConvertTz](https://pkg.go.dev/github.com/Code-Hex/synchro#ConvertTz) -- [Strftime](https://pkg.go.dev/github.com/Code-Hex/synchro#Strftime) - [NowContext](https://pkg.go.dev/github.com/Code-Hex/synchro#NowContext) - [Quarter](https://pkg.go.dev/github.com/Code-Hex/synchro#Quarter) - [Semester](https://pkg.go.dev/github.com/Code-Hex/synchro#Semester) @@ -92,6 +91,8 @@ If you have a feature request, please open an issue. It would be great if you co - [Advance](https://pkg.go.dev/github.com/Code-Hex/synchro#Time.Advance) - `Advance` allows you to specify the date and time components you want to increment and make modifications. - [Period](https://pkg.go.dev/github.com/Code-Hex/synchro#Period) +- [Strptime](https://pkg.go.dev/github.com/Code-Hex/synchro#Strptime) +- [Strftime](https://pkg.go.dev/github.com/Code-Hex/synchro#Time.Strftime) ## TODO