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.

182 lines
3.5 KiB

6 years ago
10 years ago
10 years ago
10 years ago
  1. package needle
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. const (
  7. // stored unit types
  8. Empty byte = iota
  9. Minute
  10. Hour
  11. Day
  12. Week
  13. Month
  14. Year
  15. )
  16. type TTL struct {
  17. Count byte
  18. Unit byte
  19. }
  20. var EMPTY_TTL = &TTL{}
  21. // translate a readable ttl to internal ttl
  22. // Supports format example:
  23. // 3m: 3 minutes
  24. // 4h: 4 hours
  25. // 5d: 5 days
  26. // 6w: 6 weeks
  27. // 7M: 7 months
  28. // 8y: 8 years
  29. func ReadTTL(ttlString string) (*TTL, error) {
  30. if ttlString == "" {
  31. return EMPTY_TTL, nil
  32. }
  33. ttlBytes := []byte(ttlString)
  34. unitByte := ttlBytes[len(ttlBytes)-1]
  35. countBytes := ttlBytes[0 : len(ttlBytes)-1]
  36. if '0' <= unitByte && unitByte <= '9' {
  37. countBytes = ttlBytes
  38. unitByte = 'm'
  39. }
  40. count, err := strconv.Atoi(string(countBytes))
  41. unit := toStoredByte(unitByte)
  42. return &TTL{Count: byte(count), Unit: unit}, err
  43. }
  44. // read stored bytes to a ttl
  45. func LoadTTLFromBytes(input []byte) (t *TTL) {
  46. if input[0] == 0 && input[1] == 0 {
  47. return EMPTY_TTL
  48. }
  49. return &TTL{Count: input[0], Unit: input[1]}
  50. }
  51. // read stored bytes to a ttl
  52. func LoadTTLFromUint32(ttl uint32) (t *TTL) {
  53. input := make([]byte, 2)
  54. input[1] = byte(ttl)
  55. input[0] = byte(ttl >> 8)
  56. return LoadTTLFromBytes(input)
  57. }
  58. // save stored bytes to an output with 2 bytes
  59. func (t *TTL) ToBytes(output []byte) {
  60. output[0] = t.Count
  61. output[1] = t.Unit
  62. }
  63. func (t *TTL) ToUint32() (output uint32) {
  64. if t == nil || t.Count == 0 {
  65. return 0
  66. }
  67. output = uint32(t.Count) << 8
  68. output += uint32(t.Unit)
  69. return output
  70. }
  71. func (t *TTL) String() string {
  72. if t == nil || t.Count == 0 {
  73. return ""
  74. }
  75. if t.Unit == Empty {
  76. return ""
  77. }
  78. countString := strconv.Itoa(int(t.Count))
  79. switch t.Unit {
  80. case Minute:
  81. return countString + "m"
  82. case Hour:
  83. return countString + "h"
  84. case Day:
  85. return countString + "d"
  86. case Week:
  87. return countString + "w"
  88. case Month:
  89. return countString + "M"
  90. case Year:
  91. return countString + "y"
  92. }
  93. return ""
  94. }
  95. func toStoredByte(readableUnitByte byte) byte {
  96. switch readableUnitByte {
  97. case 'm':
  98. return Minute
  99. case 'h':
  100. return Hour
  101. case 'd':
  102. return Day
  103. case 'w':
  104. return Week
  105. case 'M':
  106. return Month
  107. case 'y':
  108. return Year
  109. }
  110. return 0
  111. }
  112. func (t TTL) Minutes() uint32 {
  113. switch t.Unit {
  114. case Empty:
  115. return 0
  116. case Minute:
  117. return uint32(t.Count)
  118. case Hour:
  119. return uint32(t.Count) * 60
  120. case Day:
  121. return uint32(t.Count) * 60 * 24
  122. case Week:
  123. return uint32(t.Count) * 60 * 24 * 7
  124. case Month:
  125. return uint32(t.Count) * 60 * 24 * 30
  126. case Year:
  127. return uint32(t.Count) * 60 * 24 * 365
  128. }
  129. return 0
  130. }
  131. func SecondsToTTL(seconds int32) string {
  132. if seconds == 0 {
  133. return ""
  134. }
  135. if seconds%(3600*24*365) == 0 && seconds/(3600*24*365) < 256 {
  136. return fmt.Sprintf("%dy", seconds/(3600*24*365))
  137. }
  138. if seconds%(3600*24*30) == 0 && seconds/(3600*24*30) < 256 {
  139. return fmt.Sprintf("%dM", seconds/(3600*24*30))
  140. }
  141. if seconds%(3600*24*7) == 0 && seconds/(3600*24*7) < 256 {
  142. return fmt.Sprintf("%dw", seconds/(3600*24*7))
  143. }
  144. if seconds%(3600*24) == 0 && seconds/(3600*24) < 256 {
  145. return fmt.Sprintf("%dd", seconds/(3600*24))
  146. }
  147. if seconds%(3600) == 0 && seconds/(3600) < 256 {
  148. return fmt.Sprintf("%dh", seconds/(3600))
  149. }
  150. if seconds/60 < 256 {
  151. return fmt.Sprintf("%dm", seconds/60)
  152. }
  153. if seconds/(3600) < 256 {
  154. return fmt.Sprintf("%dh", seconds/(3600))
  155. }
  156. if seconds/(3600*24) < 256 {
  157. return fmt.Sprintf("%dd", seconds/(3600*24))
  158. }
  159. if seconds/(3600*24*7) < 256 {
  160. return fmt.Sprintf("%dw", seconds/(3600*24*7))
  161. }
  162. if seconds/(3600*24*30) < 256 {
  163. return fmt.Sprintf("%dM", seconds/(3600*24*30))
  164. }
  165. if seconds/(3600*24*365) < 256 {
  166. return fmt.Sprintf("%dy", seconds/(3600*24*365))
  167. }
  168. return ""
  169. }