From b3fb3369d463baec89290f3231a8bfcaabc7dc4c Mon Sep 17 00:00:00 2001 From: rzp-Piyush Date: Tue, 17 Dec 2024 15:50:23 +0530 Subject: [PATCH] add: supported_date_times.go --- .../i18nify-go/modules/dateTime/dateTime.go | 64 ++++++++++++------- .../modules/dateTime/dateTime_test.go | 6 +- .../modules/dateTime/format_date_time.go | 2 +- .../modules/dateTime/get_relative_time.go | 4 +- .../modules/dateTime/supported_date_times.go | 63 ++++++++++++++++++ 5 files changed, 109 insertions(+), 30 deletions(-) create mode 100644 packages/i18nify-go/modules/dateTime/supported_date_times.go diff --git a/packages/i18nify-go/modules/dateTime/dateTime.go b/packages/i18nify-go/modules/dateTime/dateTime.go index 5bd25a9b..0cf262bd 100644 --- a/packages/i18nify-go/modules/dateTime/dateTime.go +++ b/packages/i18nify-go/modules/dateTime/dateTime.go @@ -2,6 +2,7 @@ package dateTime import ( + "errors" "fmt" "time" ) @@ -38,23 +39,47 @@ type DateTimeOptions struct { IntlOptions *IntlOptions } -// parseDateTime handles parsing various date string formats -func parseDateTime(dateStr string) (time.Time, error) { - formats := []string{ - time.RFC3339, - "2006-01-02T15:04:05", - "2006-01-02", - "1/2/2006", - } +// stringToDate converts a date string into a Go time.Time object. +func stringToDate(dateString string) (time.Time, error) { + for _, format := range SupportedDateFormats { + if format.Regex != nil { + // Handle custom regex formats + if matches := format.Regex.FindStringSubmatch(dateString); matches != nil { + year := matches[format.YearIndex] + month := matches[format.MonthIndex] + day := matches[format.DayIndex] + hour, minute, second := "00", "00", "00" + + if format.HourIndex > 0 { + hour = matches[format.HourIndex] + minute = matches[format.MinuteIndex] + second = matches[format.SecondIndex] + } - for _, format := range formats { - parsed, err := time.Parse(format, dateStr) - if err == nil { - return parsed, nil + combined := fmt.Sprintf("%s-%s-%sT%s:%s:%sZ", year, month, day, hour, minute, second) + return time.Parse(time.RFC3339, combined) + } + } else if format.Format != "" { + // Handle Go's standard layouts + if parsedTime, err := time.Parse(format.Format, dateString); err == nil { + return parsedTime, nil + } } } - return time.Time{}, fmt.Errorf("invalid date format, please pass one of these formats %v", formats) + return time.Time{}, fmt.Errorf("date format not recognized: %s", dateString) +} + +// convertToStandardDate converts a date input (string or time.Time) into a standardized time.Time object. +func convertToStandardDate(dateInput interface{}) (time.Time, error) { + switch date := dateInput.(type) { + case string: + return stringToDate(date) + case time.Time: + return date, nil + default: + return time.Time{}, errors.New("unsupported date input type") + } } // GetWeekdays returns an array of weekday names starting from Sunday. @@ -68,16 +93,7 @@ func GetWeekdays() []string { return weekdays } -// ParseDateTime parses a date string and returns its components. -func ParseDateTime(dateStr, layout string) (time.Time, error) { - parsedDate, err := time.Parse(layout, dateStr) - if err != nil { - return time.Time{}, fmt.Errorf("failed to parse date: %w", err) - } - return parsedDate, nil -} - // StringToDate converts a string representation of a date into a time.Time object. -func StringToDate(dateStr string, layout string) (time.Time, error) { - return ParseDateTime(dateStr, layout) +func StringToDate(dateStr string) (time.Time, error) { + return convertToStandardDate(dateStr) } diff --git a/packages/i18nify-go/modules/dateTime/dateTime_test.go b/packages/i18nify-go/modules/dateTime/dateTime_test.go index 4ff22299..1a9936b3 100644 --- a/packages/i18nify-go/modules/dateTime/dateTime_test.go +++ b/packages/i18nify-go/modules/dateTime/dateTime_test.go @@ -38,7 +38,7 @@ func TestParseDateTime(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - _, err := parseDateTime(tt.input) + _, err := convertToStandardDate(tt.input) if tt.expectError && err == nil { t.Error("expected error but got none") } @@ -65,7 +65,7 @@ func TestStringToDate(t *testing.T) { layout := "2006-01-02 15:04:05" // Positive case - parsedDate, err := StringToDate(dateStr, layout) + parsedDate, err := StringToDate(dateStr) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -74,7 +74,7 @@ func TestStringToDate(t *testing.T) { } // Negative case - _, err = StringToDate("not-a-date", layout) + _, err = StringToDate("not-a-date") if err == nil { t.Error("expected an error for invalid date string") } diff --git a/packages/i18nify-go/modules/dateTime/format_date_time.go b/packages/i18nify-go/modules/dateTime/format_date_time.go index 1b118988..bc1c5faa 100644 --- a/packages/i18nify-go/modules/dateTime/format_date_time.go +++ b/packages/i18nify-go/modules/dateTime/format_date_time.go @@ -15,7 +15,7 @@ func FormatDateTime(dateStr string, options *DateTimeOptions) (string, error) { } // Parse the input date - parsedTime, err := parseDateTime(dateStr) + parsedTime, err := convertToStandardDate(dateStr) if err != nil { return "", fmt.Errorf("error parsing date: %v", err) } diff --git a/packages/i18nify-go/modules/dateTime/get_relative_time.go b/packages/i18nify-go/modules/dateTime/get_relative_time.go index bba352f2..62442dc2 100644 --- a/packages/i18nify-go/modules/dateTime/get_relative_time.go +++ b/packages/i18nify-go/modules/dateTime/get_relative_time.go @@ -4,11 +4,11 @@ import "fmt" // GetRelativeTime calculates the relative time string (e.g., "2 hours ago" or "in 2 hours"). func GetRelativeTime(dateStr string, options DateTimeOptions) (string, error) { - date, err := parseDateTime(dateStr) + date, err := convertToStandardDate(dateStr) if err != nil { return "", err } - baseDate, err := parseDateTime(options.BaseDate) + baseDate, err := convertToStandardDate(options.BaseDate) if err != nil { return "", err } diff --git a/packages/i18nify-go/modules/dateTime/supported_date_times.go b/packages/i18nify-go/modules/dateTime/supported_date_times.go new file mode 100644 index 00000000..042d32ee --- /dev/null +++ b/packages/i18nify-go/modules/dateTime/supported_date_times.go @@ -0,0 +1,63 @@ +package dateTime + +import ( + "regexp" + "time" +) + +// DateFormat defines the structure of supported date formats +type DateFormat struct { + Regex *regexp.Regexp + YearIndex int + MonthIndex int + DayIndex int + HourIndex int + MinuteIndex int + SecondIndex int + Format string +} + +// SupportedDateFormats holds all globally supported date formats +var SupportedDateFormats = []DateFormat{ + // Date formats + {regexp.MustCompile(`^(\d{4})/(0[1-9]|1[0-2])/(\d{2})$`), 1, 2, 3, 0, 0, 0, "YYYY/MM/DD"}, + {regexp.MustCompile(`^(\d{2})/(0[1-9]|1[0-2])/(\d{4})$`), 3, 2, 1, 0, 0, 0, "DD/MM/YYYY"}, + {regexp.MustCompile(`^(\d{4})\.(0[1-9]|1[0-2])\.(\d{2})$`), 1, 2, 3, 0, 0, 0, "YYYY.MM.DD"}, + {regexp.MustCompile(`^(\d{2})-(0[1-9]|1[0-2])-(\d{4})$`), 3, 2, 1, 0, 0, 0, "DD-MM-YYYY"}, + {regexp.MustCompile(`^(0[1-9]|1[0-2])/(\d{2})/(\d{4})$`), 3, 1, 2, 0, 0, 0, "MM/DD/YYYY"}, + {regexp.MustCompile(`^(\d{4})-(0[1-9]|1[0-2])-(\d{2})$`), 1, 2, 3, 0, 0, 0, "YYYY-MM-DD"}, + {regexp.MustCompile(`^(\d{4})\.\s*(0[1-9]|1[0-2])\.\s*(\d{2})\.\s*$`), 1, 2, 3, 0, 0, 0, "YYYY. MM. DD."}, + {regexp.MustCompile(`^(\d{2})\.(0[1-9]|1[0-2])\.(\d{4})$`), 3, 2, 1, 0, 0, 0, "DD.MM.YYYY"}, + {regexp.MustCompile(`^(0[1-9]|1[0-2])\.(\d{2})\.(\d{4})$`), 3, 1, 2, 0, 0, 0, "MM.DD.YYYY"}, + + // Timestamp formats + {regexp.MustCompile(`^(\d{4})/(0[1-9]|1[0-2])/(\d{2}) (\d{2}):(\d{2}):(\d{2})$`), 1, 2, 3, 4, 5, 6, "YYYY/MM/DD HH:MM:SS"}, + {regexp.MustCompile(`^(\d{2})/(0[1-9]|1[0-2])/(\d{4}) (\d{2}):(\d{2}):(\d{2})$`), 3, 2, 1, 4, 5, 6, "DD/MM/YYYY HH:MM:SS"}, + {regexp.MustCompile(`^(\d{4})-(0[1-9]|1[0-2])-(\d{2}) (\d{2}):(\d{2}):(\d{2})$`), 1, 2, 3, 4, 5, 6, "YYYY-MM-DD HH:MM:SS"}, + {regexp.MustCompile(`^(\d{2})-(0[1-9]|1[0-2])-(\d{4}) (\d{2}):(\d{2}):(\d{2})$`), 3, 2, 1, 4, 5, 6, "DD-MM-YYYY HH:MM:SS"}, + {regexp.MustCompile(`^(\d{4})\.(0[1-9]|1[0-2])\.(\d{2}) (\d{2}):(\d{2}):(\d{2})$`), 1, 2, 3, 4, 5, 6, "YYYY.MM.DD HH:MM:SS"}, + {regexp.MustCompile(`^(\d{2})\.(0[1-9]|1[0-2])\.(\d{4}) (\d{2}):(\d{2}):(\d{2})$`), 3, 2, 1, 4, 5, 6, "DD.MM.YYYY HH:MM:SS"}, + + // ISO 8601 Timestamp + {regexp.MustCompile(`^(\d{4})-(0[1-9]|1[0-2])-(\d{2})T(\d{2}):(\d{2}):(\d{2})$`), 1, 2, 3, 4, 5, 6, "YYYY-MM-DDTHH:MM:SS"}, + // Standard Go + {nil, 0, 0, 0, 0, 0, 0, time.Layout}, // "01/02 03:04:05PM '06 -0700" + {nil, 0, 0, 0, 0, 0, 0, time.ANSIC}, // "Mon Jan _2 15:04:05 2006" + {nil, 0, 0, 0, 0, 0, 0, time.UnixDate}, // "Mon Jan _2 15:04:05 MST 2006" + {nil, 0, 0, 0, 0, 0, 0, time.RubyDate}, // "Mon Jan 02 15:04:05 -0700 2006" + {nil, 0, 0, 0, 0, 0, 0, time.RFC822}, // "02 Jan 06 15:04 MST" + {nil, 0, 0, 0, 0, 0, 0, time.RFC822Z}, // "02 Jan 06 15:04 -0700" + {nil, 0, 0, 0, 0, 0, 0, time.RFC850}, // "Monday, 02-Jan-06 15:04:05 MST" + {nil, 0, 0, 0, 0, 0, 0, time.RFC1123}, // "Mon, 02 Jan 2006 15:04:05 MST" + {nil, 0, 0, 0, 0, 0, 0, time.RFC1123Z}, // "Mon, 02 Jan 2006 15:04:05 -0700" + {nil, 0, 0, 0, 0, 0, 0, time.RFC3339}, // "2006-01-02T15:04:05Z07:00" + {nil, 0, 0, 0, 0, 0, 0, time.RFC3339Nano}, // "2006-01-02T15:04:05.999999999Z07:00" + {nil, 0, 0, 0, 0, 0, 0, time.Kitchen}, // "3:04PM" + {nil, 0, 0, 0, 0, 0, 0, time.Stamp}, // "Jan _2 15:04:05" + {nil, 0, 0, 0, 0, 0, 0, time.StampMilli}, // "Jan _2 15:04:05.000" + {nil, 0, 0, 0, 0, 0, 0, time.StampMicro}, // "Jan _2 15:04:05.000000" + {nil, 0, 0, 0, 0, 0, 0, time.StampNano}, // "Jan _2 15:04:05.000000000" + {nil, 0, 0, 0, 0, 0, 0, "2006-01-02 15:04:05"}, // DateTime + {nil, 0, 0, 0, 0, 0, 0, "2006-01-02"}, // DateOnly + {nil, 0, 0, 0, 0, 0, 0, "15:04:05"}, // TimeOnly +}