本站源代码
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.

212 satır
4.9KB

  1. // Copyright 2015 go-swagger maintainers
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package strfmt
  15. import (
  16. "database/sql/driver"
  17. "encoding/json"
  18. "errors"
  19. "fmt"
  20. "regexp"
  21. "strconv"
  22. "strings"
  23. "time"
  24. "go.mongodb.org/mongo-driver/bson"
  25. )
  26. func init() {
  27. d := Duration(0)
  28. // register this format in the default registry
  29. Default.Add("duration", &d, IsDuration)
  30. }
  31. var (
  32. timeUnits = [][]string{
  33. {"ns", "nano"},
  34. {"us", "µs", "micro"},
  35. {"ms", "milli"},
  36. {"s", "sec"},
  37. {"m", "min"},
  38. {"h", "hr", "hour"},
  39. {"d", "day"},
  40. {"w", "wk", "week"},
  41. }
  42. timeMultiplier = map[string]time.Duration{
  43. "ns": time.Nanosecond,
  44. "us": time.Microsecond,
  45. "ms": time.Millisecond,
  46. "s": time.Second,
  47. "m": time.Minute,
  48. "h": time.Hour,
  49. "d": 24 * time.Hour,
  50. "w": 7 * 24 * time.Hour,
  51. }
  52. durationMatcher = regexp.MustCompile(`((\d+)\s*([A-Za-zµ]+))`)
  53. )
  54. // IsDuration returns true if the provided string is a valid duration
  55. func IsDuration(str string) bool {
  56. _, err := ParseDuration(str)
  57. return err == nil
  58. }
  59. // Duration represents a duration
  60. //
  61. // Duration stores a period of time as a nanosecond count, with the largest
  62. // repesentable duration being approximately 290 years.
  63. //
  64. // swagger:strfmt duration
  65. type Duration time.Duration
  66. // MarshalText turns this instance into text
  67. func (d Duration) MarshalText() ([]byte, error) {
  68. return []byte(time.Duration(d).String()), nil
  69. }
  70. // UnmarshalText hydrates this instance from text
  71. func (d *Duration) UnmarshalText(data []byte) error { // validation is performed later on
  72. dd, err := ParseDuration(string(data))
  73. if err != nil {
  74. return err
  75. }
  76. *d = Duration(dd)
  77. return nil
  78. }
  79. // ParseDuration parses a duration from a string, compatible with scala duration syntax
  80. func ParseDuration(cand string) (time.Duration, error) {
  81. if dur, err := time.ParseDuration(cand); err == nil {
  82. return dur, nil
  83. }
  84. var dur time.Duration
  85. ok := false
  86. for _, match := range durationMatcher.FindAllStringSubmatch(cand, -1) {
  87. factor, err := strconv.Atoi(match[2]) // converts string to int
  88. if err != nil {
  89. return 0, err
  90. }
  91. unit := strings.ToLower(strings.TrimSpace(match[3]))
  92. for _, variants := range timeUnits {
  93. last := len(variants) - 1
  94. multiplier := timeMultiplier[variants[0]]
  95. for i, variant := range variants {
  96. if (last == i && strings.HasPrefix(unit, variant)) || strings.EqualFold(variant, unit) {
  97. ok = true
  98. dur += (time.Duration(factor) * multiplier)
  99. }
  100. }
  101. }
  102. }
  103. if ok {
  104. return dur, nil
  105. }
  106. return 0, fmt.Errorf("unable to parse %s as duration", cand)
  107. }
  108. // Scan reads a Duration value from database driver type.
  109. func (d *Duration) Scan(raw interface{}) error {
  110. switch v := raw.(type) {
  111. // TODO: case []byte: // ?
  112. case int64:
  113. *d = Duration(v)
  114. case float64:
  115. *d = Duration(int64(v))
  116. case nil:
  117. *d = Duration(0)
  118. default:
  119. return fmt.Errorf("cannot sql.Scan() strfmt.Duration from: %#v", v)
  120. }
  121. return nil
  122. }
  123. // Value converts Duration to a primitive value ready to be written to a database.
  124. func (d Duration) Value() (driver.Value, error) {
  125. return driver.Value(int64(d)), nil
  126. }
  127. // String converts this duration to a string
  128. func (d Duration) String() string {
  129. return time.Duration(d).String()
  130. }
  131. // MarshalJSON returns the Duration as JSON
  132. func (d Duration) MarshalJSON() ([]byte, error) {
  133. return json.Marshal(time.Duration(d).String())
  134. }
  135. // UnmarshalJSON sets the Duration from JSON
  136. func (d *Duration) UnmarshalJSON(data []byte) error {
  137. if string(data) == jsonNull {
  138. return nil
  139. }
  140. var dstr string
  141. if err := json.Unmarshal(data, &dstr); err != nil {
  142. return err
  143. }
  144. tt, err := ParseDuration(dstr)
  145. if err != nil {
  146. return err
  147. }
  148. *d = Duration(tt)
  149. return nil
  150. }
  151. func (d Duration) MarshalBSON() ([]byte, error) {
  152. return bson.Marshal(bson.M{"data": d.String()})
  153. }
  154. func (d *Duration) UnmarshalBSON(data []byte) error {
  155. var m bson.M
  156. if err := bson.Unmarshal(data, &m); err != nil {
  157. return err
  158. }
  159. if data, ok := m["data"].(string); ok {
  160. rd, err := ParseDuration(data)
  161. if err != nil {
  162. return err
  163. }
  164. *d = Duration(rd)
  165. return nil
  166. }
  167. return errors.New("couldn't unmarshal bson bytes value as Date")
  168. }
  169. // DeepCopyInto copies the receiver and writes its value into out.
  170. func (d *Duration) DeepCopyInto(out *Duration) {
  171. *out = *d
  172. }
  173. // DeepCopy copies the receiver into a new Duration.
  174. func (d *Duration) DeepCopy() *Duration {
  175. if d == nil {
  176. return nil
  177. }
  178. out := new(Duration)
  179. d.DeepCopyInto(out)
  180. return out
  181. }
上海开阖软件有限公司 沪ICP备12045867号-1