Advertisement
Guest User

Untitled

a guest
Sep 17th, 2019
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.59 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. "time"
  8. )
  9.  
  10. func main() {
  11. paths := []string{
  12. "/archives/",
  13. "/archives/%-3T.dat",
  14. "/archives/%Y/%D.dat",
  15. "/archives/%Y/%0D.dat",
  16. "/archives/%Y/%m/%d.dat",
  17. "/archives/%Y/%0m/%0d.dat",
  18. "/archives/%P/%Y/%m/%d.dat",
  19. "/archives/%P/%Y/%0m/%0d.dat",
  20. "/archives/%P/%S/%Y/%m/%d.dat",
  21. "/archives/%P/%S/%Y/%0m/%0d.dat",
  22. "/archives/%P/%S/%Y/%0m/%0d.dat",
  23. "/archives/%P/%S/%Y/%0m/%d/%H-%M.dat",
  24. "/archives/%P/%S/%Y/%0m/%0d/%0H-%0M.dat",
  25. "/archives/%Y/%0D/%H/rt_%0-5M_%0-5+4M.dat",
  26. }
  27. // date = 2014-11-19 12:25:50
  28. i := Info{
  29. Pid: 907,
  30. Sid: 5432,
  31. When: time.Unix(1416396350, 0),
  32. }
  33. for _, p := range paths {
  34. f, err := Parse(p)
  35. if err != nil {
  36. fmt.Println(p, err)
  37. continue
  38. }
  39. fmt.Printf("%s: %s\n", p, f.Format(i))
  40. }
  41. }
  42.  
  43. type Info struct {
  44. UPI string
  45. Pid int
  46. Sid int
  47. When time.Time
  48. }
  49.  
  50. type Formatter interface {
  51. Format(Info) string
  52. }
  53.  
  54. func Parse(pattern string) (Formatter, error) {
  55. var (
  56. funcs []Formatter
  57. offset int
  58. )
  59. for {
  60. ix := strings.IndexByte(pattern[offset:], '%')
  61. if ix == -1 {
  62. break
  63. }
  64.  
  65. funcs = append(funcs, literal(pattern[offset:offset+ix]))
  66. offset += ix + 1
  67. if fn, n, err := parseSpecifier(pattern[offset:]); err != nil {
  68. return nil, err
  69. } else {
  70. offset += n
  71. funcs = append(funcs, fn)
  72. }
  73. }
  74. var f Formatter
  75. if len(funcs) == 0 {
  76. f = literal(pattern)
  77. } else {
  78. if offset > 0 {
  79. funcs = append(funcs, literal(pattern[offset:]))
  80. }
  81. f = formatter{
  82. funcs: funcs,
  83. }
  84. }
  85. return f, nil
  86. }
  87.  
  88. type formatter struct {
  89. str strings.Builder
  90. funcs []Formatter
  91. }
  92.  
  93. func (f formatter) Format(i Info) string {
  94. defer f.str.Reset()
  95. for _, fn := range f.funcs {
  96. f.str.WriteString(fn.Format(i))
  97. }
  98. return strings.TrimSpace(f.str.String())
  99. }
  100.  
  101. type literal string
  102.  
  103. func (i literal) Format(_ Info) string {
  104. return string(i)
  105. }
  106.  
  107. type formatFunc func(Info) string
  108.  
  109. func (f formatFunc) Format(i Info) string {
  110. return f(i)
  111. }
  112.  
  113. const (
  114. pad0 = 0
  115. pad2 = 2
  116. pad3 = 3
  117. )
  118.  
  119. // syntax: %[0][+/-0]X
  120. type specifier struct {
  121. add time.Duration
  122. sub time.Duration
  123.  
  124. padding int
  125. transform formatFunc
  126. }
  127.  
  128. func parseSpecifier(pattern string) (Formatter, int, error) {
  129. var (
  130. offset int
  131. add int
  132. sub int
  133. padding bool
  134. spec specifier
  135. )
  136. if pattern[offset] == '0' {
  137. offset++
  138. padding = true
  139. }
  140.  
  141. for {
  142. if isLetter(pattern[offset]) {
  143. break
  144. }
  145. if char := pattern[offset]; char == '-' || char == '+' {
  146. offset++
  147. if !isDigit(pattern[offset]) {
  148. return nil, 0, fmt.Errorf("invalid syntax: unexpected character %c (should be a digit)", pattern[offset])
  149. }
  150. pos := offset
  151. for isDigit(pattern[offset]) {
  152. offset++
  153. }
  154. n, err := strconv.Atoi(pattern[pos:offset])
  155. if err != nil {
  156. return nil, 0, err
  157. }
  158. if char == '-' {
  159. sub += n
  160. } else {
  161. add += n
  162. }
  163. } else {
  164. return nil, 0, fmt.Errorf("invalid syntax: unexpected character %c (should be - or +)", char)
  165. }
  166. }
  167.  
  168. switch pattern[offset] {
  169. case 'T':
  170. spec.sub = time.Duration(sub) * time.Second
  171. spec.add = time.Duration(add) * time.Second
  172. spec.transform = spec.formatTimestamp
  173. case 'Y':
  174. spec.transform = spec.formatYear
  175. case 'D':
  176. if padding {
  177. spec.padding = pad3
  178. }
  179. spec.sub = time.Duration(sub) * time.Hour * 24
  180. spec.add = time.Duration(add) * time.Hour * 24
  181. spec.transform = spec.formatDOY
  182. case 'm':
  183. if padding {
  184. spec.padding = pad2
  185. }
  186. spec.transform = spec.formatMonth
  187. case 'd':
  188. if padding {
  189. spec.padding = pad2
  190. }
  191. spec.transform = spec.formatDay
  192. case 'H':
  193. if padding {
  194. spec.padding = pad2
  195. }
  196. spec.sub = time.Duration(sub) * time.Hour
  197. spec.add = time.Duration(add) * time.Hour
  198. spec.transform = spec.formatHour
  199. case 'M':
  200. if padding {
  201. spec.padding = pad2
  202. }
  203. spec.sub = time.Duration(sub) * time.Minute
  204. spec.add = time.Duration(add) * time.Minute
  205. spec.transform = spec.formatMinute
  206. case 'P':
  207. spec.transform = spec.formatPid
  208. case 'S':
  209. spec.transform = spec.formatSid
  210. case 'U':
  211. spec.transform = spec.formatUPI
  212. default:
  213. return nil, 0, fmt.Errorf("unknown specifier: %c", pattern[offset])
  214. }
  215. offset++
  216. return spec, offset, nil
  217. }
  218.  
  219. func (s specifier) Format(i Info) string {
  220. return s.transform.Format(i)
  221. }
  222.  
  223. func (s specifier) formatTimestamp(i Info) string {
  224. w := updateTime(i.When, s.sub, s.add)
  225. return formatInt(w.Unix(), pad0)
  226. }
  227.  
  228. func (s specifier) formatYear(i Info) string {
  229. return formatInt(int64(i.When.Year()), pad0)
  230. }
  231.  
  232. func (s specifier) formatDOY(i Info) string {
  233. w := updateTime(i.When, s.sub, s.add)
  234. return formatInt(int64(w.YearDay()), s.padding)
  235. }
  236.  
  237. func (s specifier) formatMonth(i Info) string {
  238. return formatInt(int64(i.When.Month()), s.padding)
  239. }
  240.  
  241. func (s specifier) formatDay(i Info) string {
  242. return formatInt(int64(i.When.Day()), s.padding)
  243. }
  244.  
  245. func (s specifier) formatHour(i Info) string {
  246. w := updateTime(i.When, s.sub, s.add)
  247. return formatInt(int64(w.Hour()), s.padding)
  248. }
  249.  
  250. func (s specifier) formatMinute(i Info) string {
  251. w := updateTime(i.When, s.sub, s.add)
  252. return formatInt(int64(w.Minute()), s.padding)
  253. }
  254.  
  255. func (s specifier) formatPid(i Info) string {
  256. return formatInt(int64(i.Pid), pad0)
  257. }
  258.  
  259. func (s specifier) formatSid(i Info) string {
  260. return formatInt(int64(i.Sid), pad0)
  261. }
  262.  
  263. func (s specifier) formatUPI(i Info) string {
  264. return i.UPI
  265. }
  266.  
  267. func formatInt(n int64, padding int) string {
  268. if padding < 0 {
  269. padding = 0
  270. }
  271. return fmt.Sprintf("%0[2]*[1]d", n, padding)
  272. }
  273.  
  274. func updateTime(w time.Time, sub, add time.Duration) time.Time {
  275. if sub > 0 {
  276. w = w.Truncate(sub)
  277. }
  278. if add > 0 {
  279. w = w.Add(add)
  280. }
  281. return w
  282. }
  283.  
  284. func isLetter(b byte) bool {
  285. return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z')
  286. }
  287.  
  288. func isDigit(b byte) bool {
  289. return b >= '0' && b <= '9'
  290. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement