Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jul 11, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Supported date time formats are listed in: https://go.dev/src/time/format.go

```golang
// import "github.com/jftuga/dtdiff"

// example 1 - difference between two dates
dt := dtdiff.New("2024-01-01 00:00:00", "2025-12-31 23:59:59")
format, _, err := dt.DtDiff()
fmt.Println(format) // 2 years 23 hours 59 minutes 59 seconds
Expand All @@ -41,12 +43,22 @@ dt.SetBrief(true)
format, _, _ = dt.DtDiff()
fmt.Println(format) // 2Y23h59m59s

// example 2 - duration
from := "2024-01-01 00:00:00"
period := "1 day 1 hour 2 minutes 3 seconds" // can also use: "1D1h2m3s"
future, _ := dtdiff.Add(from, period)
fmt.Println(future) // 2024-01-02 01:02:03
past, _ := dtdiff.Sub(from, period)
fmt.Println(past) // 2023-12-30 22:57:57

// example 3 duration with five intervals
from := "2024-06-28T04:25:41Z"
period := "1M1W1h1m2s"
recurrence := 5
all, _ := dtdiff.AddWithRecurrence(from, period, recurrence)
for _, a := range all {
fmt.Println(a)
}
```

**Full Example:**
Expand Down Expand Up @@ -76,6 +88,7 @@ Flag Group 1 (mutually exclusive with Flag Group 2):
Flag Group 2:
-A, --add string add: a duration to use with -F, such as '1 day 2 hours 3 seconds'
-F, --from string a base date, time or datetime to use with -A or -S
-R, --recurrence recurrence interval
-S, --sub string subtract: a duration to use with -F, such as '5 months 4 weeks 3 days'

Durations:
Expand All @@ -94,6 +107,8 @@ examples: 1Y2M3W4D5h6m7s8ms9us1ns, "1Y 2M 3W 4D 5h 6m 7s 8ms 9us 1ns"
1. one line with start and end separated by a comma
2. two lines with start on the first line and end on the second line

**Note:** The `-n` switch along with `-R` will use a comma-delimited output

## Examples

```shell
Expand Down
51 changes: 48 additions & 3 deletions cmd/dtdiff/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Flag Group 1 (mutually exclusive with Flag Group 2):
{{FlagUsagesCustom .LocalFlags "start" "end" "stdin" "brief" | trimTrailingWhitespaces}}

Flag Group 2:
{{FlagUsagesCustom .LocalFlags "from" "add" "sub" | trimTrailingWhitespaces}}
{{FlagUsagesCustom .LocalFlags "from" "add" "sub" "recurrence" | trimTrailingWhitespaces}}

Durations:
years months weeks days
Expand All @@ -55,6 +55,7 @@ var (
from string
add string
sub string
recurrence int
noNewline bool
readFromStdin bool
brief bool
Expand All @@ -69,12 +70,21 @@ var (
computeStartEnd(start, end, brief)
return
}

if len(from) > 0 && len(add) > 0 {
computeAddSub(from, add, 0)
if recurrence > 0 {
computeAddSubWithRecurrence(from, add, 0, recurrence)
} else {
computeAddSub(from, add, 0)
}
return
}
if len(from) > 0 && len(sub) > 0 {
computeAddSub(from, sub, 1)
if recurrence > 0 {
computeAddSubWithRecurrence(from, sub, 1, recurrence)
} else {
computeAddSub(from, sub, 1)
}
return
}
fmt.Fprintln(os.Stderr, usageMsg)
Expand Down Expand Up @@ -122,6 +132,7 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&from, "from", "F", "", "a base date, time or datetime to use with -A or -S")
rootCmd.PersistentFlags().StringVarP(&add, "add", "A", "", "add: a duration to use with -F, such as '1 day 2 hours 3 seconds'")
rootCmd.PersistentFlags().StringVarP(&sub, "sub", "S", "", "subtract: a duration to use with -F, such as '5 months 4 weeks 3 days'")
rootCmd.PersistentFlags().IntVarP(&recurrence, "recurrence", "R", 0, "recurrence interval")
rootCmd.PersistentFlags().BoolVarP(&noNewline, "nonewline", "n", false, "do not output a newline character")
rootCmd.PersistentFlags().BoolVarP(&readFromStdin, "stdin", "i", false, "read from STDIN instead of using -s/-e")
rootCmd.PersistentFlags().BoolVarP(&brief, "brief", "b", false, "output in brief format, such as: 1Y2M3D4h5m6s7ms8us9ns")
Expand All @@ -133,15 +144,19 @@ func init() {
rootCmd.MarkFlagsMutuallyExclusive("stdin", "from")
rootCmd.MarkFlagsMutuallyExclusive("stdin", "add")
rootCmd.MarkFlagsMutuallyExclusive("stdin", "sub")
rootCmd.MarkFlagsMutuallyExclusive("stdin", "recurrence")
rootCmd.MarkFlagsMutuallyExclusive("from", "start")
rootCmd.MarkFlagsMutuallyExclusive("from", "end")
rootCmd.MarkFlagsMutuallyExclusive("recurrence", "start")
rootCmd.MarkFlagsMutuallyExclusive("recurrence", "end")
rootCmd.MarkFlagsMutuallyExclusive("add", "start")
rootCmd.MarkFlagsMutuallyExclusive("add", "end")
rootCmd.MarkFlagsMutuallyExclusive("sub", "start")
rootCmd.MarkFlagsMutuallyExclusive("sub", "end")
rootCmd.MarkFlagsMutuallyExclusive("brief", "from")
rootCmd.MarkFlagsMutuallyExclusive("brief", "add")
rootCmd.MarkFlagsMutuallyExclusive("brief", "sub")
rootCmd.MarkFlagsMutuallyExclusive("brief", "recurrence")

versionTemplate := fmt.Sprintf("%s v%s\n%s\n", dtdiff.PgmName, dtdiff.PgmVersion, dtdiff.PgmUrl)
rootCmd.SetVersionTemplate(versionTemplate)
Expand Down Expand Up @@ -220,3 +235,33 @@ func computeAddSub(from, period string, index int) {
fmt.Println(format)
}
}

// computeAddSubWithRecurrence is similar to computeAddSub
// but returns a slice of date/time intervals
// when -n is invoked, a comma-delimited output is used
// index 0 = add; index = 1 = sub
func computeAddSubWithRecurrence(from, period string, index, recurrence int) {
var format []string
var err error
if index == 0 {
format, err = dtdiff.AddWithRecurrence(from, period, recurrence)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
} else {
format, err = dtdiff.SubWithRecurrence(from, period, recurrence)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

if noNewline {
fmt.Print(strings.Join(format, ","))
} else {
for _, f := range format {
fmt.Println(f)
}
}
}
38 changes: 26 additions & 12 deletions cmd/example/expected-output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,32 @@
2024-03-04T00:00:00Z 2024-06-12T23:59:59Z 2423h59m59s 14W2D23h59m59s
2024-01-01 13:00:00 2024-02-29 13:00:00 1416h0m0s 8 weeks 3 days
2024-01-01 13:00:00 2024-02-29 13:00:00 1416h0m0s 8W3D
2020-01-01 2024-06-19 05:53:40 39148h53m40s 4 years 24 weeks 3 days 4 hours 53 minutes 40 seconds
2020-01-01 2024-06-19 05:53:40 39148h53m40s 4Y24W3D4h53m40s
2020-01-01 2024-06-28 06:38:44 39365h38m44s 4 years 25 weeks 5 days 5 hours 38 minutes 44 seconds
2020-01-01 2024-06-28 06:38:44 39365h38m44s 4Y25W5D5h38m44s

==========================================================================================

2024-01-01 00:00:00 1 hour 30 minutes 45 seconds 2024-01-01 01:30:45 -0600 CST 2023-12-31 22:29:15 -0600 CST
2024-01-01 00:00:00 12 hours 2024-01-01 12:00:00 -0600 CST 2023-12-31 12:00:00 -0600 CST
2024-01-01 00:00:00 1 day 1 hour 2 minutes 3 seconds 2024-01-02 01:02:03 -0600 CST 2023-12-30 22:57:57 -0600 CST
2024-01-01 00:00:00 5 hours 5 minutes 5 seconds 2024-01-01 05:05:05 -0600 CST 2023-12-31 18:54:55 -0600 CST
2024-01-01 00:00:00 58 seconds 2024-01-01 00:00:58 -0600 CST 2023-12-31 23:59:02 -0600 CST
2024-01-01 00:00:00 1 minute 30 seconds 2024-01-01 00:01:30 -0600 CST 2023-12-31 23:58:30 -0600 CST
2024-01-01 00:00:00 123 microseconds 2024-01-01 00:00:00.000123 -0600 CST 2023-12-31 23:59:59.999877 -0600 CST
2024-01-01 00:00:00 1 minute 2 seconds 345 milliseconds 2024-01-01 00:01:02.345 -0600 CST 2023-12-31 23:58:57.655 -0600 CST
2024-01-01 00:00:00 45 seconds 2024-01-01 00:00:45 -0600 CST 2023-12-31 23:59:15 -0600 CST
2024-01-01 00:00:00 1 minute 5 seconds 2024-01-01 00:01:05 -0600 CST 2023-12-31 23:58:55 -0600 CST
2024-01-01 00:00:00 1 hour 30 minutes 45 seconds 2024-01-01 01:30:45 -0500 EST 2023-12-31 22:29:15 -0500 EST
2024-01-01 00:00:00 12 hours 2024-01-01 12:00:00 -0500 EST 2023-12-31 12:00:00 -0500 EST
2024-01-01 00:00:00 1 day 1 hour 2 minutes 3 seconds 2024-01-02 01:02:03 -0500 EST 2023-12-30 22:57:57 -0500 EST
2024-01-01 00:00:00 5 hours 5 minutes 5 seconds 2024-01-01 05:05:05 -0500 EST 2023-12-31 18:54:55 -0500 EST
2024-01-01 00:00:00 58 seconds 2024-01-01 00:00:58 -0500 EST 2023-12-31 23:59:02 -0500 EST
2024-01-01 00:00:00 1 minute 30 seconds 2024-01-01 00:01:30 -0500 EST 2023-12-31 23:58:30 -0500 EST
2024-01-01 00:00:00 123 microseconds 2024-01-01 00:00:00.000123 -0500 EST 2023-12-31 23:59:59.999877 -0500 EST
2024-01-01 00:00:00 1 minute 2 seconds 345 milliseconds 2024-01-01 00:01:02.345 -0500 EST 2023-12-31 23:58:57.655 -0500 EST
2024-01-01 00:00:00 45 seconds 2024-01-01 00:00:45 -0500 EST 2023-12-31 23:59:15 -0500 EST
2024-01-01 00:00:00 1 minute 5 seconds 2024-01-01 00:01:05 -0500 EST 2023-12-31 23:58:55 -0500 EST

==========================================================================================

2024-08-04 05:26:43 +0000 UTC
2024-09-11 06:27:45 +0000 UTC
2024-10-18 07:28:47 +0000 UTC
2024-11-25 08:29:49 +0000 UTC
2025-01-01 09:30:51 +0000 UTC

2024-05-21 03:24:39 +0000 UTC
2024-04-14 02:23:37 +0000 UTC
2024-03-07 01:22:35 +0000 UTC
2024-01-31 00:21:33 +0000 UTC
2023-12-24 05:20:31 +0000 UTC
31 changes: 31 additions & 0 deletions cmd/example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,31 @@ import (
"time"
)

func testRecurrence() {
from := "2024-06-28T04:25:41Z"
period := "1M1W1h1m2s"
recurrence := 5
all, err := dtdiff.AddWithRecurrence(from, period, recurrence)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
for _, a := range all {
fmt.Println(a)
}

fmt.Println()

all, err = dtdiff.SubWithRecurrence(from, period, recurrence)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
for _, a := range all {
fmt.Println(a)
}
}

func main() {
allStarts := []string{"8:30AM", "11:12:13", "2024-03-04T00:00:00Z", "2024-01-01 13:00:00", "2020-01-01"}
allEnds := []string{"4:35PM", "14:15:16", "2024-06-12T23:59:59Z", "2024-02-29 13:00:00", time.Now().String()[:19]}
Expand Down Expand Up @@ -65,4 +90,10 @@ func main() {
fmt.Printf("%s %35s %37s %37s\n", from, period, future, past)
}

fmt.Println()
fmt.Println("==========================================================================================")
fmt.Println()

testRecurrence()

}
30 changes: 29 additions & 1 deletion dtdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

const (
PgmName string = "dtdiff"
PgmVersion string = "1.1.0"
PgmVersion string = "1.2.0"
PgmUrl string = "https://github.com/jftuga/dtdiff"
)

Expand Down Expand Up @@ -275,3 +275,31 @@ func Add(from, period string) (string, error) {
func Sub(from, period string) (string, error) {
return calculate(from, period, 1)
}

// calculateWithRecurrence similar to calculate, but returns
// a slice of multiple past or future date/times at intervals of length 'period'
// index==0 then Add; index==1 then Sub
func calculateWithRecurrence(from, period string, index, recurrence int) ([]string, error) {
var all []string
var err error
for i := 0; i < recurrence; i++ {
from, err = calculate(from, period, index)
if err != nil {
return nil, err
}
all = append(all, from)
}
return all, nil
}

// AddWithRecurrence similar to Add, but returns a slice
// of multiple future dates/times at intervals of length 'period'
func AddWithRecurrence(from, period string, recurrence int) ([]string, error) {
return calculateWithRecurrence(from, period, 0, recurrence)
}

// SubWithRecurrence similar to Sub, but returns a slice
// of multiple past dates/times at intervals of length 'period'
func SubWithRecurrence(from, period string, recurrence int) ([]string, error) {
return calculateWithRecurrence(from, period, 1, recurrence)
}
31 changes: 31 additions & 0 deletions dtdiff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,28 @@ func testAddSubContains(t *testing.T, from, period, correctAdd, correctSub strin
}
}

func testAddSubWithRecurrence(t *testing.T, from, period string, correctAdd, correctSub []string, recurrence int) {
future, err := AddWithRecurrence(from, period, recurrence)
if err != nil {
t.Error(err)
}
for i := range len(future) {
if !strings.Contains(future[i], correctAdd[i]) {
t.Errorf("[from: %v] [computed: %v] does not contain: [correct: %v]", from, future, correctAdd)
}
}

past, err := SubWithRecurrence(from, period, recurrence)
if err != nil {
t.Error(err)
}
for j := range len(past) {
if !strings.Contains(past[j], correctSub[j]) {
t.Errorf("[from: %v] [computed: %v] does not contain: [correct: %v]", from, past, correctSub)
}
}
}

func TestTwoTimesSameDay(t *testing.T) {
start := "12:00:00"
end := "15:30:45"
Expand Down Expand Up @@ -174,3 +196,12 @@ func TestDurationNanoseconds(t *testing.T) {
testAddSubContains(t, from, period, correctAdd, correctSub)
testAddSubContains(t, from, briefPeriod, correctAdd, correctSub)
}

func TestWithRecurrence(t *testing.T) {
from := "2024-06-28T04:25:41Z"
period := "1M1W1h1m2s"
recurrence := 3
allCorrectAdd := []string{"2024-08-04 05:26:43", "2024-09-11 06:27:45", "2024-10-18 07:28:47"}
allCorrectSub := []string{"2024-05-21 03:24:39", "2024-04-14 02:23:37", "2024-03-07 01:22:35"}
testAddSubWithRecurrence(t, from, period, allCorrectAdd, allCorrectSub, recurrence)
}