Erster Commit.

This commit is contained in:
Marco Kittel 2025-06-22 19:33:30 +02:00
commit 32b4c00942
5 changed files with 265 additions and 0 deletions

3
logger/go.mod Normal file
View File

@ -0,0 +1,3 @@
module gittea.marcokittel.de/elio/eliotools/logger
go 1.24.4

69
logger/logger.go Normal file
View File

@ -0,0 +1,69 @@
package logger
import (
"fmt"
"runtime/debug"
"strings"
"time"
)
type Logger interface {
Info(message string)
Infof(format string, a ...any)
Warning(message string)
Critical(message string)
Fatal(message string)
}
type ML struct {
}
func (m *ML) sendMsg(message string) {
// Da die CSV Dateien RFC3339 nutzen, wechsel ich darauf im Log der
// Konsistenz wegen.
msg := "# " + time.Now().Format(time.RFC3339) + "\n* " + message
fmt.Println(msg)
}
func (m *ML) sendMsgWithStack(message string) {
msg := message
stack := string(debug.Stack())
msg += "\n\n### *** Stack ***\n\n\n >" + indentStacktrace(stack)
msg += "\n________"
m.sendMsg(msg)
}
func (m *ML) Info(message string) {
m.sendMsgWithStack("Info: " + message)
}
func (m *ML) Infof(format string, a ...any) {
msg := fmt.Sprintf(format, a)
m.sendMsgWithStack("Info: " + msg)
}
func (m *ML) Warning(message string) {
m.sendMsgWithStack("Warning: " + message)
}
func (m *ML) Critical(message string) {
stack := string(debug.Stack())
m.sendMsgWithStack("Critical: " + message + indentStacktrace(stack))
}
func (m *ML) Fatal(message string) {
m.sendMsgWithStack("Fatal" + message)
panic(message)
}
func indentStacktrace(stack string) string {
lines := strings.Split(stack, "\n")
for i := 1; i < len(lines); i++ {
lines[i] = " " + lines[i]
}
return strings.Join(lines, "\n")
}
func NewMarcoLogger() Logger {
log := ML{}
return &log
}

3
tools/go.mod Normal file
View File

@ -0,0 +1,3 @@
module gittea.marcokittel.de/elio/eliotools/tools
go 1.24.4

41
tools/tools.go Normal file
View File

@ -0,0 +1,41 @@
package main
import (
"errors"
"os"
"regexp"
"time"
)
func IsFilenameValid(filename string) bool {
pattern := `^20[2-9][0-9]-(0[1-9]|1[0-2])-(0[0-9]|1[0-9]|2[0-9]|3[0-1])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]:[0-5][0-9])((\+00:00)|(\-00:00)|(\-0[3,9]:30)|(\-1[0-2]:00)|(-0[0-9]:00)|(\+0[0-9]:00)|(\+0[09,03,04,05,06]:30)|(\+10:30)|(\+1[0-4]:00)|(\+0[5,8]:45)|(\+12:45))-(CH|DE|EU|AT)-(stock|delivery).csv$`
re := regexp.MustCompile(pattern)
return re.MatchString(filename)
}
func CheckDir(path string) (bool, error) {
info, err := os.Stat(path)
if err == nil {
return info.IsDir(), nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func RFC3339StringToTime(rfc3339str string) (time.Time, error) {
const MINUS12STUNDEN = -43200
const PLUS24STUNDEN = 50400
t, err := time.Parse("2006-01-02T15:04:05-07:00", rfc3339str)
if err != nil {
happybirthday := time.Date(1981, time.March, 1, 4, 15, 0, 0, time.UTC)
return happybirthday, err
}
_, offset := t.Zone()
if offset < MINUS12STUNDEN || offset > PLUS24STUNDEN {
return time.Date(1981, time.March, 1, 4, 15, 0, 0, time.UTC), errors.New("timezone offset must be between -12:00 and +14:0")
}
return t, nil
}

149
tools/tools_test.go Normal file
View File

@ -0,0 +1,149 @@
package main
import (
"testing"
)
func TestHello(t *testing.T) {
testcases := []struct {
testcase string
valid bool
}{
{testcase: "2023-11-09T15:02:17+00:00-CH-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+00:00-DE-delivery.csv", valid: true},
{testcase: "2023-11-09T15:02:17+00:00-EU-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+00:00-AT-stock.csv", valid: true},
}
//"2023-11-09T15:02:17+00:00-CH-stock.csv"
for i, tc := range testcases {
result := IsFilenameValid(tc.testcase)
if result != tc.valid {
t.Errorf("Testcase %d is not valid, but %s must be valid!", i, tc.testcase)
}
}
}
func TestValidTimeZonesWith30(t *testing.T) {
testcases := []struct {
testcase string
valid bool
}{
{testcase: "2023-11-09T15:02:17+03:30-EU-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+04:30-DE-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+05:30-DE-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+06:30-CH-delivery.csv", valid: true},
{testcase: "2023-11-09T15:02:17+09:30-CH-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+10:30-AT-stock.csv", valid: true},
}
for i, tc := range testcases {
result := IsFilenameValid(tc.testcase)
if result != tc.valid {
t.Errorf("Testcase %d is not valid, but %s must be valid!", i, tc.testcase)
}
}
}
func TestValidDateTime(t *testing.T) {
testcases := []struct {
testcase string
valid bool
}{
{testcase: "2025-11-29T23:02:17+03:30-EU-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+04:30-DE-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+05:30-DE-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+06:30-CH-delivery.csv", valid: true},
{testcase: "2023-11-09T15:02:17+09:30-CH-stock.csv", valid: true},
{testcase: "2023-11-09T15:02:17+10:30-AT-delivery.csv", valid: true},
}
for i, tc := range testcases {
result := IsFilenameValid(tc.testcase)
if result != tc.valid {
t.Errorf("Testcase %d is not valid, but %s must be valid!", i, tc.testcase)
}
}
}
func TestInValidTimeZonesWith30(t *testing.T) {
testcases := []struct {
testcase string
valid bool
}{
{testcase: "2023-11-09T15:02:17+02:30-EU-stock.csv", valid: false},
{testcase: "2023-11-09T15:02:17+01:30-DE-stock.csv", valid: false},
{testcase: "2023-11-09T15:02:17+23:30-DE-stock.csv", valid: false},
{testcase: "2023-11-09T15:02:17+07:30-CH-stock.csv", valid: false},
{testcase: "2023-11-09T15:02:17+08:30-CH-stock.csv", valid: false},
{testcase: "2023-11-09T15:02:17+12:30-AT-stock.csv", valid: false},
}
for i, tc := range testcases {
result := IsFilenameValid(tc.testcase)
if result != tc.valid {
t.Errorf("Testcase %d is not valid, but %s must be valid!", i, tc.testcase)
}
}
}
func TestInValidDateTimeWith(t *testing.T) {
testcases := []struct {
testcase string
valid bool
}{
{testcase: "2000-11-03T15:02:17+00:00-EU-stock.csv", valid: false},
{testcase: "2026-11-03T15:60:17+00:00-EU-stock.csv", valid: false},
{testcase: "2025-00-03T15:20:17+00:00-EU-stock.csv", valid: false},
{testcase: "2100-01-03T23:59:17+00:00-EU-stock.csv", valid: false},
{testcase: "2027-2-03T15:20:17+00:00-EU-stock.csv", valid: false},
{testcase: "2023-11-09T15:02:51+00:01-AT-stock.csv", valid: false},
}
for i, tc := range testcases {
result := IsFilenameValid(tc.testcase)
if result != tc.valid {
t.Errorf("Testcase %d is not valid, but %s must be valid!", i, tc.testcase)
}
}
}
func TestValidRFC3339StringToTime(t *testing.T) {
testcases := []struct {
testcase string
valid bool
}{
{testcase: "2000-11-03T15:02:17+00:00", valid: true},
{testcase: "2026-11-03T15:02:17+03:30", valid: true},
{testcase: "2026-12-03T23:02:17+05:30", valid: true},
{testcase: "2026-11-03T15:02:17-12:00", valid: true},
{testcase: "2026-11-03T23:59:17+14:00", valid: true},
}
for i, tc := range testcases {
result, err := RFC3339StringToTime(tc.testcase)
if err != nil || tc.valid == false {
t.Errorf("Testcase %d is not valid, but %s must be valid!", i, result)
}
}
}
func TestInValidRFC3339StringToTime(t *testing.T) {
testcases := []struct {
testcase string
invalid bool
}{
{testcase: "2026-13-03T23:02:17+05:30", invalid: true},
{testcase: "2026-00-03T23:02:17+05:30", invalid: true},
{testcase: "2026-03-03T23:02:17+99:30", invalid: true},
{testcase: "2026-03-03T23:02:17+99:00", invalid: true},
{testcase: "2026-03-03T23:02:17+16:00", invalid: true},
}
for i, tc := range testcases {
result, err := RFC3339StringToTime(tc.testcase)
if err == nil && tc.invalid {
t.Errorf("Testcase %d is valid, but %s must be invalid!", i, result.String())
}
}
}