volume_ttl.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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 (t *TTL) ToSeconds() uint64 {
  96. switch t.Unit {
  97. case Empty:
  98. return 0
  99. case Minute:
  100. return uint64(t.Count) * 60
  101. case Hour:
  102. return uint64(t.Count) * 60 * 60
  103. case Day:
  104. return uint64(t.Count) * 60 * 24 * 60
  105. case Week:
  106. return uint64(t.Count) * 60 * 24 * 7 * 60
  107. case Month:
  108. return uint64(t.Count) * 60 * 24 * 30 * 60
  109. case Year:
  110. return uint64(t.Count) * 60 * 24 * 365 * 60
  111. }
  112. return 0
  113. }
  114. func toStoredByte(readableUnitByte byte) byte {
  115. switch readableUnitByte {
  116. case 'm':
  117. return Minute
  118. case 'h':
  119. return Hour
  120. case 'd':
  121. return Day
  122. case 'w':
  123. return Week
  124. case 'M':
  125. return Month
  126. case 'y':
  127. return Year
  128. }
  129. return 0
  130. }
  131. func (t TTL) Minutes() uint32 {
  132. switch t.Unit {
  133. case Empty:
  134. return 0
  135. case Minute:
  136. return uint32(t.Count)
  137. case Hour:
  138. return uint32(t.Count) * 60
  139. case Day:
  140. return uint32(t.Count) * 60 * 24
  141. case Week:
  142. return uint32(t.Count) * 60 * 24 * 7
  143. case Month:
  144. return uint32(t.Count) * 60 * 24 * 30
  145. case Year:
  146. return uint32(t.Count) * 60 * 24 * 365
  147. }
  148. return 0
  149. }
  150. func SecondsToTTL(seconds int32) string {
  151. if seconds == 0 {
  152. return ""
  153. }
  154. if seconds%(3600*24*365) == 0 && seconds/(3600*24*365) < 256 {
  155. return fmt.Sprintf("%dy", seconds/(3600*24*365))
  156. }
  157. if seconds%(3600*24*30) == 0 && seconds/(3600*24*30) < 256 {
  158. return fmt.Sprintf("%dM", seconds/(3600*24*30))
  159. }
  160. if seconds%(3600*24*7) == 0 && seconds/(3600*24*7) < 256 {
  161. return fmt.Sprintf("%dw", seconds/(3600*24*7))
  162. }
  163. if seconds%(3600*24) == 0 && seconds/(3600*24) < 256 {
  164. return fmt.Sprintf("%dd", seconds/(3600*24))
  165. }
  166. if seconds%(3600) == 0 && seconds/(3600) < 256 {
  167. return fmt.Sprintf("%dh", seconds/(3600))
  168. }
  169. if seconds/60 < 256 {
  170. return fmt.Sprintf("%dm", seconds/60)
  171. }
  172. if seconds/(3600) < 256 {
  173. return fmt.Sprintf("%dh", seconds/(3600))
  174. }
  175. if seconds/(3600*24) < 256 {
  176. return fmt.Sprintf("%dd", seconds/(3600*24))
  177. }
  178. if seconds/(3600*24*7) < 256 {
  179. return fmt.Sprintf("%dw", seconds/(3600*24*7))
  180. }
  181. if seconds/(3600*24*30) < 256 {
  182. return fmt.Sprintf("%dM", seconds/(3600*24*30))
  183. }
  184. if seconds/(3600*24*365) < 256 {
  185. return fmt.Sprintf("%dy", seconds/(3600*24*365))
  186. }
  187. return ""
  188. }