Skip to content
Snippets Groups Projects
Select Git revision
  • bf093221e6df5fbe4ba353ed1b705e915e7ad118
  • main default protected
  • v1.302.0
  • v1.301.0
  • v1.300.0
  • v1.299.0
  • v1.298.0
  • v1.297.0
  • v1.296.0
  • v1.295.0
  • v1.294.0
  • v1.293.0
  • v1.292.0
  • v1.291.0
  • v1.290.0
  • v1.289.0
  • v1.288.0
  • v1.287.0
  • v1.286.0
  • v1.285.0
  • v1.284.0
  • v1.283.0
22 results

date_utils.go

Blame
  • date_utils.go 6.72 KiB
    package date_utils
    
    import (
    	"github.com/araddon/dateparse"
    	"reflect"
    	"strconv"
    	"time"
    )
    
    const TimeZoneString = "Africa/Johannesburg"
    
    var currentLocation *time.Location
    
    func DateLayoutYearMonthDayTimeT() string {
    	layout := "2006-01-02T15:04:05"
    	return layout
    }
    
    func DateLayoutYearMonthDayTimeTZ() string {
    	layout := "2006-01-02T15:04:05Z"
    	return layout
    }
    
    func DateLayoutYearMonthDayTimeMillisecondTZ() string {
    	layout := "2006-01-02T15:04:05.000Z"
    	return layout
    }
    
    func DateLayoutDB() string {
    	return "2006-01-02 15:04:05.000000-07"
    }
    
    func DateLayoutYearMonthDayTimeTimezone() string {
    	layout := "2006-01-02 15:04:05-07:00"
    	return layout
    }
    
    func DateLayoutForDB() string {
    	layout := "2006-01-02 15:04:05-07"
    	return layout
    }
    
    func DateLayoutYearMonthDayTime() string {
    	layout := "2006-01-02 15:04:05"
    	return layout
    }
    
    func DateLayoutFilenameSafe() string {
    	layout := "02-Jan-2006-15h04"
    	return layout
    }
    
    func DateLayoutYearMonthDay() string {
    	layout := "2006-01-02"
    	return layout
    }
    
    func DateLayoutTime() string {
    	layout := "15:04:05"
    	return layout
    }
    
    func DateLayoutHumanReadable() string {
    	layout := "02 Jan 2006"
    	return layout
    }
    
    func DateLayoutHumanReadableWithTime() string {
    	layout := "02 Jan 2006 15:04"
    	return layout
    }
    
    func DateLayoutTrimmed() string {
    	layout := "20060102150405"
    	return layout
    }
    
    func DateDBFormattedString(date time.Time) string {
    	return date.Format(DateLayoutDB())
    }
    
    func DateDBFormattedStringDateOnly(date time.Time) string {
    	return date.Format(DateLayoutYearMonthDay())
    }
    
    func CurrentLocation() *time.Location {
    	if currentLocation == nil {
    		currentLocation, _ = time.LoadLocation(TimeZoneString)
    	}
    	return currentLocation
    }
    
    func DateLocal(date *time.Time) {
    	if date == nil {
    		return
    	}
    	*date = (*date).In(CurrentLocation())
    }
    
    func CurrentDate() time.Time {
    	currentDate := time.Now().In(CurrentLocation())
    	return currentDate
    }
    
    func DateEqual(date1, date2 time.Time) bool {
    	y1, m1, d1 := date1.Date()
    	y2, m2, d2 := date2.Date()
    	return y1 == y2 && m1 == m2 && d1 == d2
    }
    
    // TimeBefore determines whether a (string format HH:mm) is earlier than b (string format HH:mm)
    func TimeBefore(a string, b string) bool {
    	if len(a) < 5 || len(b) < 5 {
    		return false // can't detemrine before/after
    	}
    
    	hoursA, _ := strconv.Atoi(a[0:2])
    	hoursB, _ := strconv.Atoi(b[0:2])
    
    	minA, _ := strconv.Atoi(a[3:5])
    	minB, _ := strconv.Atoi(b[3:5])
    
    	if hoursA == hoursB {
    		return minA < minB
    	}
    
    	return hoursA < hoursB
    }
    
    // ConvertToNoDateTimeString  - Converts a PSQL Time type to Go Time type
    func ConvertToNoDateTimeString(timeString *string) (*string, error) {
    	parsedTime, err := time.Parse("15:04:05", *timeString)
    	if err != nil {
    		return nil, err
    	}
    	formattedTime := parsedTime.Format("15:04")
    	return &formattedTime, nil
    }
    
    // ParseTimeString attempts to parse the string as the default date-time format, or as a date only format
    func ParseTimeString(timeString string) (time.Time, error) {
    	// Try using the defined formats in date_utils
    	parsedTime, err := time.Parse(DateLayoutYearMonthDayTimeMillisecondTZ(), timeString)
    	if err != nil {
    		parsedTime, err = time.Parse(DateLayoutYearMonthDayTimeT(), timeString)
    		if err != nil {
    			parsedTime, err = time.Parse(DateLayoutYearMonthDayTimeTZ(), timeString)
    			if err != nil {
    				parsedTime, err = time.Parse(DateLayoutYearMonthDay(), timeString)
    				if err != nil {
    					parsedTime, err = time.Parse(DateLayoutYearMonthDayTime(), timeString)
    					if err != nil {
    						parsedTime, err = time.Parse(DateLayoutYearMonthDayTimeTimezone(), timeString)
    						if err != nil {
    							parsedTime, err = time.Parse(DateLayoutDB(), timeString)
    						}
    					}
    				}
    			}
    		}
    	}
    	if err != nil {
    		// Try using other date formats from dateparse library
    		parsedTime, err = dateparse.ParseAny(timeString)
    	}
    
    	return parsedTime, err
    }
    
    func FormatTimestampsWithTimeZoneOnStructRecursively(object any, location *time.Location) error {
    	var objectValue reflect.Value
    	objectValue = reflect.ValueOf(object)
    	for objectValue.Kind() == reflect.Pointer ||
    		objectValue.Kind() == reflect.Interface {
    		objectValue = objectValue.Elem()
    	}
    
    	err := formatTimestampsWithTimeZoneOnStruct(objectValue, location)
    	return err
    }
    
    func formatTimestampsWithTimeZoneOnStruct(structValue reflect.Value, location *time.Location) error {
    	numF := structValue.NumField()
    	for i := 0; i < numF; i++ {
    		fieldValue := structValue.Field(i)
    		fieldType := fieldValue.Type()
    		fieldKind := fieldValue.Type().Kind()
    
    		timeType := reflect.TypeOf(time.Time{})
    		if fieldType == timeType && !fieldValue.IsZero() {
    			fieldValue.Set(reflect.ValueOf(fieldValue.Interface().(time.Time).In(location)))
    			continue
    		}
    
    		timePointerType := reflect.TypeOf(&time.Time{})
    		if fieldType == timePointerType && !fieldValue.IsNil() {
    			timeInLocation := fieldValue.Interface().(*time.Time).In(location)
    			timeInLocationPointer := reflect.ValueOf(timeInLocation)
    
    			fieldPointer := fieldValue.Elem()
    			fieldPointer.Set(timeInLocationPointer)
    			continue
    		}
    
    		if fieldKind == reflect.Slice {
    			// Loop over the slice items
    			err := formatTimestampsWithTimeZoneInSlice(fieldValue, location)
    			if err != nil {
    				return err
    			}
    			continue
    		} else if fieldKind == reflect.Struct {
    			err := formatTimestampsWithTimeZoneOnStruct(fieldValue, location)
    			if err != nil {
    				return err
    			}
    			continue
    		} else if fieldKind == reflect.Interface || fieldKind == reflect.Pointer {
    			var objectValue reflect.Value
    			objectValue = fieldValue.Elem()
    			if objectValue.Kind() == reflect.Slice {
    				err := formatTimestampsWithTimeZoneInSlice(objectValue, location)
    				if err != nil {
    					return err
    				}
    			} else if objectValue.Kind() == reflect.Struct {
    				err := formatTimestampsWithTimeZoneOnStruct(objectValue, location)
    				if err != nil {
    					return err
    				}
    			}
    			continue
    		}
    
    	}
    
    	return nil
    }
    
    func formatTimestampsWithTimeZoneInSlice(fieldValue reflect.Value, location *time.Location) error {
    	for j := 0; j < fieldValue.Len(); j++ {
    		sliceItem := fieldValue.Index(j)
    
    		if sliceItem.IsValid() {
    			var sliceItemValue reflect.Value
    			if sliceItem.Kind() == reflect.Ptr && sliceItem.IsValid() {
    				// Dereference the pointer
    				sliceItemValue = sliceItem.Elem()
    			} else {
    				sliceItemValue = sliceItem
    			}
    
    			if sliceItemValue.IsValid() {
    				sliceItemKind := sliceItemValue.Kind()
    				sliceItemType := sliceItemValue.Type()
    
    				// Check whether we have a slice of time.Time, and set the location if we do.
    				if sliceItemType == reflect.TypeOf(time.Time{}) {
    					sliceItemValue.Set(reflect.ValueOf(sliceItemValue.Interface().(time.Time).In(location)))
    					continue
    				}
    
    				if sliceItemKind == reflect.Struct {
    					err := formatTimestampsWithTimeZoneOnStruct(sliceItemValue, location)
    					if err != nil {
    						return err
    					}
    				}
    			}
    		}
    	}
    	return nil
    }