Skip to content

Commit

Permalink
feat: add the 'fmt' command to reformat a date/time
Browse files Browse the repository at this point in the history
  • Loading branch information
jftuga committed Jul 22, 2024
1 parent fbdee45 commit 3bc5e5c
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@
# Go workspace file
go.work
go.work.sum

# Project exclusions
cmd/dtmate/cmd/README.md
26 changes: 24 additions & 2 deletions DateTimeMate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package DateTimeMate

import (
"github.com/golang-module/carbon/v2"
"github.com/lestrrat-go/strftime"
"github.com/tkuchiki/parsetime"
"strings"
)

Expand Down Expand Up @@ -34,9 +36,9 @@ var abbrevMap = [][]string{
{"year", "Y"},
}

// convertRelativeDateToActual converts "yesterday", "today", "tomorrow"
// ConvertRelativeDateToActual converts "yesterday", "today", "tomorrow"
// into actual dates; yesterday and tomorrow are -/+ 24 hours of current time
func convertRelativeDateToActual(from string) string {
func ConvertRelativeDateToActual(from string) string {
switch strings.ToLower(from) {
case "now":
return carbon.Now().String()
Expand Down Expand Up @@ -66,3 +68,23 @@ func shrinkPeriod(period string) string {
func removeTrailingS(s string) string {
return strings.TrimSuffix(s, "s")
}

// Reformat the source string to match the strftime outputFormat
// Ex: "2024-07-22 08:21:44", "%v %r" => "22-Jul-2024 08:21:44 AM"
func Reformat(source string, outputFormat string) (string, error) {
source = ConvertRelativeDateToActual(source)
f, err := strftime.New(outputFormat)
if err != nil {
return "", err
}
p, err := parsetime.NewParseTime()
if err != nil {
return "", err
}
s, err := p.Parse(source)
if err != nil {
return "", err

}
return f.FormatString(s), nil
}
40 changes: 40 additions & 0 deletions DateTimeMate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,43 @@ func TestShrinkPeriod(t *testing.T) {
}
}
}

func testFormat(t *testing.T, source, outputFormat, correct string) {
t.Helper()
computed, err := Reformat(source, outputFormat)
if err != nil {
t.Error(err)
}
if computed != correct {
t.Errorf("[computed: %v] != [correct: %v]", computed, correct)
}
}

func TestFormatCommand(t *testing.T) {
source := "2024-07-22 08:21:44"
fmt := "%T %D"
correct := "08:21:44 07/22/24"
testFormat(t, source, fmt, correct)

fmt = "%v %r"
correct = "22-Jul-2024 08:21:44 AM"
testFormat(t, source, fmt, correct)

fmt = "%Y%m%d.%H%M%S"
correct = "20240722.082144"
testFormat(t, source, fmt, correct)

source = "2024-02-29T23:59:59Z"
fmt = "%Y%m%d.%H%M%S"
correct = "20240229.235959"
testFormat(t, source, fmt, correct)

fmt = "%Z"
correct = "UTC"
testFormat(t, source, fmt, correct)

source = "Mon Jul 22 08:40:33 EDT 2024"
fmt = "%Z %z"
correct = "EDT -0400"
testFormat(t, source, fmt, correct)
}
89 changes: 89 additions & 0 deletions cmd/dtmate/cmd/fmt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package cmd

import (
"fmt"
"github.com/jftuga/DateTimeMate"
"github.com/spf13/cobra"
"os"
)

var fmtCmd = &cobra.Command{
Use: "fmt [date/time] [format specifiers]",
Short: "reformat a date/time",
Run: func(cmd *cobra.Command, args []string) {
if optFmtList {
listConversionsSpecifiers()
return
}
reformat(args[0], args[1])
},
}

var optFmtList bool

func init() {
rootCmd.AddCommand(fmtCmd)
fmtCmd.Flags().BoolVarP(&optFmtList, "list", "l", false, "list supported conversion specifiers")
}

// listConversionsSpecifiers the list was copied from:
// https://github.com/lestrrat-go/strftime
func listConversionsSpecifiers() {
list := [][]string{
[]string{`%A`, `national representation of the full weekday name`},
[]string{`%a`, `national representation of the abbreviated weekday`},
[]string{`%B`, `national representation of the full month name`},
[]string{`%b`, `national representation of the abbreviated month name`},
[]string{`%C`, `(year / 100) as decimal number; single digits are preceded by a zero`},
[]string{`%c`, `national representation of time and date`},
[]string{`%D`, `equivalent to %m/%d/%y`},
[]string{`%d`, `day of the month as a decimal number (01-31)`},
[]string{`%e`, `the day of the month as a decimal number (1-31); single digits are preceded by a blank`},
[]string{`%F`, `equivalent to %Y-%m-%d`},
[]string{`%H`, `the hour (24-hour clock) as a decimal number (00-23)`},
[]string{`%h`, `same as %b`},
[]string{`%I`, `the hour (12-hour clock) as a decimal number (01-12)`},
[]string{`%j`, `the day of the year as a decimal number (001-366)`},
[]string{`%k`, `the hour (24-hour clock) as a decimal number (0-23); single digits are preceded by a blank`},
[]string{`%l`, `the hour (12-hour clock) as a decimal number (1-12); single digits are preceded by a blank`},
[]string{`%M`, `the minute as a decimal number (00-59)`},
[]string{`%m`, `the month as a decimal number (01-12)`},
[]string{`%n`, `a newline`},
[]string{`%p`, `national representation of either 'ante meridiem' (a.m.) or 'post meridiem' (p.m.) as appropriate.`},
[]string{`%R`, `equivalent to %H:%M`},
[]string{`%r`, `equivalent to %I:%M:%S %p`},
[]string{`%S`, `the second as a decimal number (00-60)`},
[]string{`%T`, `equivalent to %H:%M:%S`},
[]string{`%t`, `a tab`},
[]string{`%U`, `the week number of the year (Sunday as the first day of the week) as a decimal number (00-53)`},
[]string{`%u`, `the weekday (Monday as the first day of the week) as a decimal number (1-7)`},
[]string{`%V`, `the week number of the year (Monday as the first day of the week) as a decimal number (01-53)`},
[]string{`%v`, `equivalent to %e-%b-%Y`},
[]string{`%W`, `the week number of the year (Monday as the first day of the week) as a decimal number (00-53)`},
[]string{`%w`, `the weekday (Sunday as the first day of the week) as a decimal number (0-6)`},
[]string{`%X`, `national representation of the time`},
[]string{`%x`, `national representation of the date`},
[]string{`%Y`, `the year with century as a decimal number`},
[]string{`%y`, `the year without century as a decimal number (00-99)`},
[]string{`%Z`, `the time zone name`},
[]string{`%z`, `the time zone offset from UTC`},
[]string{`%%`, `a '%'`},
}

for i := 0; i < len(list); i++ {
fmt.Printf("%s %s\n", list[i][0], list[i][1])
}
}

func reformat(source, outputFormat string) {
result, err := DateTimeMate.Reformat(source, outputFormat)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if optRootNoNewline {
fmt.Print(result)
} else {
fmt.Println(result)
}
}
4 changes: 2 additions & 2 deletions diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (diff *Diff) String() string {
func (diff *Diff) CalculateDiff() (string, time.Duration, error) {
var start, end time.Time

alpha := carbon.Parse(convertRelativeDateToActual(diff.Start))
alpha := carbon.Parse(ConvertRelativeDateToActual(diff.Start))
if alpha.Error != nil {
// fmt.Println("alpha:", alpha.Error)
p, err := parsetime.NewParseTime()
Expand All @@ -66,7 +66,7 @@ func (diff *Diff) CalculateDiff() (string, time.Duration, error) {
start = alpha.StdTime()
}

omega := carbon.Parse(convertRelativeDateToActual(diff.End))
omega := carbon.Parse(ConvertRelativeDateToActual(diff.End))
if omega.Error != nil {
// fmt.Println("omega:", omega.Error)
p, err := parsetime.NewParseTime()
Expand Down
6 changes: 3 additions & 3 deletions dur.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (dur *Dur) addOrSub(op int) ([]string, error) {
var f, u time.Time
var err error

until := convertRelativeDateToActual(dur.Until)
until := ConvertRelativeDateToActual(dur.Until)
p, err := parsetime.NewParseTime()
if err != nil {
return nil, err
Expand All @@ -144,7 +144,7 @@ func (dur *Dur) addOrSub(op int) ([]string, error) {
return nil, err
}

from := convertRelativeDateToActual(dur.From)
from := ConvertRelativeDateToActual(dur.From)
for {
from, err = calculate(from, dur.Period, op)
if err != nil {
Expand Down Expand Up @@ -222,7 +222,7 @@ func calculate(from, period string, index int) (string, error) {
}
}

from = convertRelativeDateToActual(from)
from = ConvertRelativeDateToActual(from)
p, err := parsetime.NewParseTime()
if err != nil {
return "", err
Expand Down

0 comments on commit 3bc5e5c

Please sign in to comment.