You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
2.4 KiB

  1. package models
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "strconv"
  7. "strings"
  8. "time"
  9. )
  10. var TimeOfDayTimeZone = time.UTC
  11. type TimeOfDay int
  12. func (t *TimeOfDay) UnmarshalJSON(v []byte) error {
  13. if bytes.Equal(v, []byte("null")) {
  14. *t = -1
  15. }
  16. var str string
  17. err := json.Unmarshal(v, &str)
  18. if err != nil {
  19. var n int
  20. err = json.Unmarshal(v, &n)
  21. if err != nil {
  22. return err
  23. }
  24. if n < -1 && n >= 86400 {
  25. return fmt.Errorf("value outside range 0..86400: %d", n)
  26. }
  27. }
  28. t2, err := ParseTimeOfDay(str)
  29. if err != nil {
  30. return err
  31. }
  32. *t = t2
  33. return nil
  34. }
  35. func (t TimeOfDay) MarshalJSON() ([]byte, error) {
  36. if t.IsNever() {
  37. return []byte("null"), nil
  38. }
  39. return json.Marshal(t.String())
  40. }
  41. const Never = TimeOfDay(-1)
  42. func (t *TimeOfDay) String() string {
  43. if *t < 0 {
  44. return "n/a"
  45. }
  46. return fmt.Sprintf("%02d:%02d:%02d", *t/3600, (*t/60)%60, *t%60)
  47. }
  48. func (t *TimeOfDay) StringPtr() *string {
  49. if *t < 0 {
  50. return nil
  51. }
  52. s := t.String()
  53. return &s
  54. }
  55. func (t TimeOfDay) IsNever() bool {
  56. return t == Never
  57. }
  58. func (t TimeOfDay) IsBetween(from TimeOfDay, to TimeOfDay) bool {
  59. if from == to {
  60. return t == from
  61. } else if from > to {
  62. return t >= from || t <= to
  63. } else {
  64. return t >= from && t <= to
  65. }
  66. }
  67. func CurrentTimeOfDay() TimeOfDay {
  68. return TimeOfDayFromDate(time.Now().In(TimeOfDayTimeZone))
  69. }
  70. func TimeOfDayFromDate(date time.Time) TimeOfDay {
  71. localDate := date.In(TimeOfDayTimeZone)
  72. return NewTimeOfDay(localDate.Hour(), localDate.Minute(), localDate.Second())
  73. }
  74. func NewTimeOfDay(hours, minutes, seconds int) TimeOfDay {
  75. return TimeOfDay(((hours % 24) * 3600) + ((minutes % 60) * 60) + seconds)
  76. }
  77. func ParseTimeOfDayPtr(str *string) (TimeOfDay, error) {
  78. if str == nil {
  79. return Never, nil
  80. }
  81. return ParseTimeOfDay(*str)
  82. }
  83. func ParseTimeOfDay(str string) (TimeOfDay, error) {
  84. if str == "" || str == "n/a" || str == "N/A" {
  85. return -1, nil
  86. }
  87. split := strings.SplitN(str, ":", 4)
  88. res := 0
  89. n, err := strconv.Atoi(split[0])
  90. if err != nil {
  91. return Never, err
  92. }
  93. res += n * 3600
  94. if len(split) >= 2 {
  95. n, err := strconv.Atoi(split[1])
  96. if err != nil {
  97. return Never, err
  98. }
  99. res += n * 60
  100. }
  101. if len(split) >= 3 {
  102. n, err := strconv.Atoi(split[2])
  103. if err != nil {
  104. return Never, err
  105. }
  106. res += n
  107. }
  108. if res >= 86400 || res < 0 {
  109. return Never, fmt.Errorf("invalid time of day string %s (=%d)", str, res)
  110. }
  111. return TimeOfDay(res), nil
  112. }