Compare commits

...

6 Commits

7 changed files with 160 additions and 48 deletions

74
langext/base62.go Normal file
View File

@@ -0,0 +1,74 @@
package langext
import (
"crypto/rand"
"errors"
"math"
"math/big"
"strings"
)
var (
base62Base = uint64(62)
base62CharacterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
)
func RandBase62(rlen int) string {
bi52 := big.NewInt(int64(len(base62CharacterSet)))
randMax := big.NewInt(math.MaxInt64)
r := ""
for i := 0; i < rlen; i++ {
v, err := rand.Int(rand.Reader, randMax)
if err != nil {
panic(err)
}
r += string(base62CharacterSet[v.Mod(v, bi52).Int64()])
}
return r
}
func EncodeBase62(num uint64) string {
if num == 0 {
return "0"
}
b := make([]byte, 0)
// loop as long the num is bigger than zero
for num > 0 {
r := num % base62Base
num -= r
num /= base62Base
b = append([]byte{base62CharacterSet[int(r)]}, b...)
}
return string(b)
}
func DecodeBase62(str string) (uint64, error) {
if str == "" {
return 0, errors.New("empty string")
}
result := uint64(0)
for _, v := range str {
result *= base62Base
pos := strings.IndexRune(base62CharacterSet, v)
if pos == -1 {
return 0, errors.New("invalid character: " + string(v))
}
result += uint64(pos)
}
return result, nil
}

View File

@@ -30,3 +30,34 @@ func CompareIntArr(arr1 []int, arr2 []int) bool {
return false
}
func CompareArr[T OrderedConstraint](arr1 []T, arr2 []T) bool {
for i := 0; i < len(arr1) || i < len(arr2); i++ {
if i < len(arr1) && i < len(arr2) {
if arr1[i] < arr2[i] {
return true
} else if arr1[i] > arr2[i] {
return false
} else {
continue
}
}
if i < len(arr1) {
return true
} else { // if i < len(arr2)
return false
}
}
return false
}

21
langext/coords.go Normal file
View File

@@ -0,0 +1,21 @@
package langext
import "math"
func DegToRad(deg float64) float64 {
return deg * (math.Pi / 180.0)
}
func RadToDeg(rad float64) float64 {
return rad / (math.Pi * 180.0)
}
func GeoDistance(lon1 float64, lat1 float64, lon2 float64, lat2 float64) float64 {
var d1 = DegToRad(lat1)
var num1 = DegToRad(lon1)
var d2 = DegToRad(lat2)
var num2 = DegToRad(lon2) - num1
var d3 = math.Pow(math.Sin((d2-d1)/2.0), 2.0) + math.Cos(d1)*math.Cos(d2)*math.Pow(math.Sin(num2/2.0), 2.0)
return 6376500.0 * (2.0 * math.Atan2(math.Sqrt(d3), math.Sqrt(1.0-d3)))
}

View File

@@ -3,8 +3,6 @@ package langext
import (
"crypto/rand"
"io"
"math"
"math/big"
)
func RandBytes(size int) []byte {
@@ -15,24 +13,3 @@ func RandBytes(size int) []byte {
}
return b
}
func RandBase62(rlen int) string {
ecs := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
bi52 := big.NewInt(int64(len(ecs)))
randMax := big.NewInt(math.MaxInt64)
r := ""
for i := 0; i < rlen; i++ {
v, err := rand.Int(rand.Reader, randMax)
if err != nil {
panic(err)
}
r += string(ecs[v.Mod(v, bi52).Int64()])
}
return r
}

5
termext/osutil_linux.go Normal file
View File

@@ -0,0 +1,5 @@
package termext
func enableColor() bool {
return true
}

View File

@@ -17,14 +17,14 @@ func init() {
}
// TimeToDatePart returns a timestamp at the start of the day which contains t (= 00:00:00)
func TimeToDatePart(t time.Time) time.Time {
t = t.In(TimezoneBerlin)
func TimeToDatePart(t time.Time, tz *time.Location) time.Time {
t = t.In(tz)
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
}
// TimeToWeekStart returns a timestamp at the start of the week which contains t (= Monday 00:00:00)
func TimeToWeekStart(t time.Time) time.Time {
t = TimeToDatePart(t)
func TimeToWeekStart(t time.Time, tz *time.Location) time.Time {
t = TimeToDatePart(t, tz)
delta := time.Duration(((int64(t.Weekday()) + 6) % 7) * 24 * int64(time.Hour))
t = t.Add(-1 * delta)
@@ -33,32 +33,32 @@ func TimeToWeekStart(t time.Time) time.Time {
}
// TimeToMonthStart returns a timestamp at the start of the month which contains t (= yyyy-MM-00 00:00:00)
func TimeToMonthStart(t time.Time) time.Time {
t = t.In(TimezoneBerlin)
func TimeToMonthStart(t time.Time, tz *time.Location) time.Time {
t = t.In(tz)
return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
}
// TimeToMonthEnd returns a timestamp at the end of the month which contains t (= yyyy-MM-31 23:59:59.999999999)
func TimeToMonthEnd(t time.Time) time.Time {
return TimeToMonthStart(t).AddDate(0, 1, 0).Add(-1)
func TimeToMonthEnd(t time.Time, tz *time.Location) time.Time {
return TimeToMonthStart(t, tz).AddDate(0, 1, 0).Add(-1)
}
// TimeToYearStart returns a timestamp at the start of the year which contains t (= yyyy-01-01 00:00:00)
func TimeToYearStart(t time.Time) time.Time {
t = t.In(TimezoneBerlin)
func TimeToYearStart(t time.Time, tz *time.Location) time.Time {
t = t.In(tz)
return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, t.Location())
}
// TimeToYearEnd returns a timestamp at the end of the month which contains t (= yyyy-12-31 23:59:59.999999999)
func TimeToYearEnd(t time.Time) time.Time {
return TimeToYearStart(t).AddDate(1, 0, 0).Add(-1)
func TimeToYearEnd(t time.Time, tz *time.Location) time.Time {
return TimeToYearStart(t, tz).AddDate(1, 0, 0).Add(-1)
}
// IsSameDayIncludingDateBoundaries returns true if t1 and t2 are part of the same day (TZ/Berlin), the boundaries of the day are
// inclusive, this means 2021-09-15T00:00:00 is still part of the day 2021-09-14
func IsSameDayIncludingDateBoundaries(t1 time.Time, t2 time.Time) bool {
dp1 := TimeToDatePart(t1)
dp2 := TimeToDatePart(t2)
func IsSameDayIncludingDateBoundaries(t1 time.Time, t2 time.Time, tz *time.Location) bool {
dp1 := TimeToDatePart(t1, tz)
dp2 := TimeToDatePart(t2, tz)
if dp1.Equal(dp2) {
return true
@@ -72,9 +72,9 @@ func IsSameDayIncludingDateBoundaries(t1 time.Time, t2 time.Time) bool {
}
// IsDatePartEqual returns true if a and b have the same date part (`yyyy`, `MM` and `dd`)
func IsDatePartEqual(a time.Time, b time.Time) bool {
yy1, mm1, dd1 := a.In(TimezoneBerlin).Date()
yy2, mm2, dd2 := b.In(TimezoneBerlin).Date()
func IsDatePartEqual(a time.Time, b time.Time, tz *time.Location) bool {
yy1, mm1, dd1 := a.In(tz).Date()
yy2, mm2, dd2 := b.In(tz).Date()
return yy1 == yy2 && mm1 == mm2 && dd1 == dd2
}
@@ -82,9 +82,9 @@ func IsDatePartEqual(a time.Time, b time.Time) bool {
// WithTimePart returns a timestamp with the date-part (`yyyy`, `MM`, `dd`) from base
// and the time (`HH`, `mm`, `ss`) from the parameter
func WithTimePart(base time.Time, hour, minute, second int) time.Time {
datepart := TimeToDatePart(base)
datepart := TimeToDatePart(base, base.Location())
delta := time.Duration(hour*int(time.Hour) + minute*int(time.Minute) + second*int(time.Second))
delta := time.Duration(int64(hour)*int64(time.Hour) + int64(minute)*int64(time.Minute) + int64(second)*int64(time.Second))
return datepart.Add(delta)
}
@@ -92,23 +92,23 @@ func WithTimePart(base time.Time, hour, minute, second int) time.Time {
// CombineDateAndTime returns a timestamp with the date-part (`yyyy`, `MM`, `dd`) from the d parameter
// and the time (`HH`, `mm`, `ss`) from the t parameter
func CombineDateAndTime(d time.Time, t time.Time) time.Time {
datepart := TimeToDatePart(d)
datepart := TimeToDatePart(d, d.Location())
delta := time.Duration(t.Hour()*int(time.Hour) + t.Minute()*int(time.Minute) + t.Second()*int(time.Second) + t.Nanosecond()*int(time.Nanosecond))
delta := time.Duration(int64(t.Hour())*int64(time.Hour) + int64(t.Minute())*int64(time.Minute) + int64(t.Second())*int64(time.Second) + int64(t.Nanosecond())*int64(time.Nanosecond))
return datepart.Add(delta)
}
// IsSunday returns true if t is a sunday (in TZ/Berlin)
func IsSunday(t time.Time) bool {
if t.In(TimezoneBerlin).Weekday() == time.Sunday {
func IsSunday(t time.Time, tz *time.Location) bool {
if t.In(tz).Weekday() == time.Sunday {
return true
}
return false
}
func DurationFromTime(hours int, minutes int, seconds int) time.Duration {
return time.Duration(hours*int(time.Hour) + minutes*int(time.Minute) + seconds*int(time.Second))
return time.Duration(int64(hours)*int64(time.Hour) + int64(minutes)*int64(time.Minute) + int64(seconds)*int64(time.Second))
}
func Min(a time.Time, b time.Time) time.Time {
@@ -131,3 +131,7 @@ func UnixFloatSeconds(v float64) time.Time {
sec, dec := math.Modf(v)
return time.Unix(int64(sec), int64(dec*(1e9)))
}
func FloorTime(t time.Time) time.Time {
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
}