Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
3a17edfaf0
|
|||
3320a9c19d
|
|||
8dcd8a270a
|
4
go.mod
4
go.mod
@@ -6,7 +6,7 @@ require (
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/glebarez/go-sqlite v1.22.0 // only needed for tests -.-
|
||||
github.com/jmoiron/sqlx v1.4.0
|
||||
github.com/rs/xid v1.5.0
|
||||
github.com/rs/xid v1.6.0
|
||||
github.com/rs/zerolog v1.33.0
|
||||
go.mongodb.org/mongo-driver v1.16.1
|
||||
golang.org/x/crypto v0.26.0
|
||||
@@ -45,7 +45,7 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
|
4
go.sum
4
go.sum
@@ -175,6 +175,8 @@ github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtos
|
||||
github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -184,6 +186,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
|
||||
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
|
||||
|
@@ -1,5 +1,5 @@
|
||||
package goext
|
||||
|
||||
const GoextVersion = "0.0.506"
|
||||
const GoextVersion = "0.0.509"
|
||||
|
||||
const GoextVersionTimestamp = "2024-08-22T11:45:02+0200"
|
||||
const GoextVersionTimestamp = "2024-08-26T14:35:49+0200"
|
||||
|
@@ -1353,7 +1353,7 @@ func typeFields(t reflect.Type, tagkey string) structFields {
|
||||
|
||||
var jsonfilter []string
|
||||
jsonfilterTag := sf.Tag.Get("jsonfilter")
|
||||
if jsonfilterTag != "" && jsonfilterTag != "-" {
|
||||
if jsonfilterTag != "" {
|
||||
jsonfilter = strings.Split(jsonfilterTag, ",")
|
||||
}
|
||||
|
||||
|
15
langext/io.go
Normal file
15
langext/io.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package langext
|
||||
|
||||
import "io"
|
||||
|
||||
type nopCloser struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (n nopCloser) Close() error {
|
||||
return nil // no op
|
||||
}
|
||||
|
||||
func WriteNopCloser(w io.Writer) io.WriteCloser {
|
||||
return nopCloser{w}
|
||||
}
|
@@ -2,6 +2,9 @@ package timeext
|
||||
|
||||
import "time"
|
||||
|
||||
// YearDifference calculates the difference between two timestamps in years.
|
||||
// = t1 - t2
|
||||
// returns a float value
|
||||
func YearDifference(t1 time.Time, t2 time.Time, tz *time.Location) float64 {
|
||||
|
||||
yDelta := float64(t1.Year() - t2.Year())
|
||||
@@ -11,3 +14,31 @@ func YearDifference(t1 time.Time, t2 time.Time, tz *time.Location) float64 {
|
||||
|
||||
return yDelta + (processT1 - processT2)
|
||||
}
|
||||
|
||||
// MonthDifference calculates the difference between two timestamps in months.
|
||||
// = t1 - t2
|
||||
// returns a float value
|
||||
func MonthDifference(t1 time.Time, t2 time.Time) float64 {
|
||||
|
||||
yDelta := float64(t1.Year() - t2.Year())
|
||||
mDelta := float64(t1.Month() - t2.Month())
|
||||
|
||||
dDelta := float64(0)
|
||||
|
||||
t1MonthDays := DaysInMonth(t1)
|
||||
t2MonthDays := DaysInMonth(t2)
|
||||
|
||||
if t2.Year() > t1.Year() || (t2.Year() == t1.Year() && t2.Month() > t1.Month()) {
|
||||
dDelta -= 1
|
||||
dDelta += float64(t1MonthDays-t1.Day()) / float64(t1MonthDays)
|
||||
dDelta += float64(t2.Day()) / float64(t2MonthDays)
|
||||
} else if t2.Year() < t1.Year() || (t2.Year() == t1.Year() && t2.Month() < t1.Month()) {
|
||||
dDelta -= 1
|
||||
dDelta += float64(t1.Day()) / float64(t1MonthDays)
|
||||
dDelta += float64(t2MonthDays-t2.Day()) / float64(t2MonthDays)
|
||||
} else {
|
||||
dDelta += float64(t1.Day()-t2.Day()) / float64(t1MonthDays)
|
||||
}
|
||||
|
||||
return yDelta*12 + mDelta + dDelta
|
||||
}
|
||||
|
@@ -81,3 +81,63 @@ func epsilonEquals(a, b float64) bool {
|
||||
epsilon := 0.01
|
||||
return math.Abs(a-b) < epsilon
|
||||
}
|
||||
|
||||
func TestMonthDifferenceSameDate(t *testing.T) {
|
||||
t1 := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
t2 := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
expected := 0.0
|
||||
result := MonthDifference(t2, t1)
|
||||
if !epsilonEquals(result, expected) {
|
||||
t.Errorf("Expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthDifferenceSameMonth(t *testing.T) {
|
||||
t1 := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
t2 := time.Date(2022, 1, 31, 0, 0, 0, 0, time.UTC)
|
||||
expected := 0.967741935483871 // Approximation of 30/31 days
|
||||
result := MonthDifference(t2, t1)
|
||||
if !epsilonEquals(result, expected) {
|
||||
t.Errorf("Expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthDifferenceDifferentMonthsSameYear(t *testing.T) {
|
||||
t1 := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
t2 := time.Date(2022, 3, 1, 0, 0, 0, 0, time.UTC)
|
||||
expected := 2.0
|
||||
result := MonthDifference(t2, t1)
|
||||
if !epsilonEquals(result, expected) {
|
||||
t.Errorf("Expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthDifferenceDifferentYears(t *testing.T) {
|
||||
t1 := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
|
||||
t2 := time.Date(2022, 2, 1, 0, 0, 0, 0, time.UTC)
|
||||
expected := 2.0
|
||||
result := MonthDifference(t2, t1)
|
||||
if !epsilonEquals(result, expected) {
|
||||
t.Errorf("Expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthDifferenceT1BeforeT2(t *testing.T) {
|
||||
t1 := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
t2 := time.Date(2022, 6, 1, 0, 0, 0, 0, time.UTC)
|
||||
expected := 5.0
|
||||
result := MonthDifference(t2, t1)
|
||||
if !epsilonEquals(result, expected) {
|
||||
t.Errorf("Expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthDifferenceT1AfterT2(t *testing.T) {
|
||||
t1 := time.Date(2022, 6, 1, 0, 0, 0, 0, time.UTC)
|
||||
t2 := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
expected := -5.0
|
||||
result := MonthDifference(t2, t1)
|
||||
if !epsilonEquals(result, expected) {
|
||||
t.Errorf("Expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
@@ -184,3 +184,10 @@ func AddYears(t time.Time, yearCount float64, tz *time.Location) time.Time {
|
||||
|
||||
return t.Add(time.Duration(float64(t1.Sub(t0)) * floatCount))
|
||||
}
|
||||
|
||||
func DaysInMonth(t time.Time) int {
|
||||
// https://stackoverflow.com/a/73882035/1761622
|
||||
|
||||
y, m, _ := t.Date()
|
||||
return time.Date(y, m+1, 0, 0, 0, 0, 0, time.UTC).Day()
|
||||
}
|
||||
|
@@ -191,3 +191,39 @@ func TestCombineDateAndTime_CombineDifferentParts(t *testing.T) {
|
||||
t.Errorf("Expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaysInMonth_31Days(t *testing.T) {
|
||||
date := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC) // January
|
||||
expected := 31
|
||||
result := DaysInMonth(date)
|
||||
if result != expected {
|
||||
t.Errorf("Expected %d but got %d", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaysInMonth_30Days(t *testing.T) {
|
||||
date := time.Date(2022, 4, 1, 0, 0, 0, 0, time.UTC) // April
|
||||
expected := 30
|
||||
result := DaysInMonth(date)
|
||||
if result != expected {
|
||||
t.Errorf("Expected %d but got %d", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaysInMonth_FebruaryLeapYear(t *testing.T) {
|
||||
date := time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC) // February in a leap year
|
||||
expected := 29
|
||||
result := DaysInMonth(date)
|
||||
if result != expected {
|
||||
t.Errorf("Expected %d but got %d", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaysInMonth_FebruaryNonLeapYear(t *testing.T) {
|
||||
date := time.Date(2021, 2, 1, 0, 0, 0, 0, time.UTC) // February in a non-leap year
|
||||
expected := 28
|
||||
result := DaysInMonth(date)
|
||||
if result != expected {
|
||||
t.Errorf("Expected %d but got %d", expected, result)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user