units.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package duration_fmt
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. // DefaultUnitsCoder default units coder using `":"` as PluralSep and `","` as UnitsSep
  7. var DefaultUnitsCoder = UnitsCoder{":", ","}
  8. // Unit the pair of singular and plural units
  9. type Unit struct {
  10. Singular, Plural string
  11. }
  12. // Units duration units
  13. type Units struct {
  14. Year, Week, Day, Hour, Minute,
  15. Second, Millisecond, Microsecond Unit
  16. }
  17. // Units return a slice of units
  18. func (u Units) Units() []Unit {
  19. return []Unit{u.Year, u.Week, u.Day, u.Hour, u.Minute,
  20. u.Second, u.Millisecond, u.Microsecond}
  21. }
  22. // UnitsCoder the units encoder and decoder
  23. type UnitsCoder struct {
  24. // PluralSep char to sep singular and plural pair.
  25. // Example with char `":"`: `"year:year"` (english) or `"mês:meses"` (portuguese)
  26. PluralSep,
  27. // UnitsSep char to sep units (singular and plural pairs).
  28. // Example with char `","`: `"year:year,week:weeks"` (english) or `"mês:meses,semana:semanas"` (portuguese)
  29. UnitsSep string
  30. }
  31. // Encode encodes input Units to string
  32. // Examples with `UnitsCoder{PluralSep: ":", UnitsSep = ","}`
  33. // - singular and plural pair units: `"year:wers,week:weeks,day:days,hour:hours,minute:minutes,second:seconds,millisecond:millliseconds,microsecond:microsseconds"`
  34. func (coder UnitsCoder) Encode(units Units) string {
  35. var pairs = make([]string, 8)
  36. for i, u := range units.Units() {
  37. pairs[i] = u.Singular + coder.PluralSep + u.Plural
  38. }
  39. return strings.Join(pairs, coder.UnitsSep)
  40. }
  41. // Decode decodes input string to Units.
  42. // The input must follow the following formats:
  43. // - Unit format (singular and plural pair)
  44. // - must singular (the plural receives 's' character as suffix)
  45. // - singular and plural: separated by `PluralSep` char
  46. // Example with char `":"`: `"year:year"` (english) or `"mês:meses"` (portuguese)
  47. // - Units format (pairs of Year, Week, Day, Hour, Minute,
  48. // Second, Millisecond and Microsecond units) separated by `UnitsSep` char
  49. // - Examples with `UnitsCoder{PluralSep: ":", UnitsSep = ","}`
  50. // - must singular units: `"year,week,day,hour,minute,second,millisecond,microsecond"`
  51. // - mixed units: `"year,week:weeks,day,hour,minute:minutes,second,millisecond,microsecond"`
  52. // - singular and plural pair units: `"year:wers,week:weeks,day:days,hour:hours,minute:minutes,second:seconds,millisecond:millliseconds,microsecond:microsseconds"`
  53. func (coder UnitsCoder) Decode(s string) (units Units, err error) {
  54. parts := strings.Split(s, coder.UnitsSep)
  55. if len(parts) != 8 {
  56. err = fmt.Errorf("bad parts length")
  57. return units, err
  58. }
  59. var parse = func(name, part string, u *Unit) bool {
  60. ps := strings.Split(part, coder.PluralSep)
  61. switch len(ps) {
  62. case 1:
  63. u.Singular, u.Plural = ps[0], ps[0]
  64. case 2:
  65. u.Singular, u.Plural = ps[0], ps[1]
  66. default:
  67. err = fmt.Errorf("bad unit %q pair length", name)
  68. return false
  69. }
  70. return true
  71. }
  72. if !parse("Year", parts[0], &units.Year) {
  73. return units, err
  74. }
  75. if !parse("Week", parts[1], &units.Week) {
  76. return units, err
  77. }
  78. if !parse("Day", parts[2], &units.Day) {
  79. return units, err
  80. }
  81. if !parse("Hour", parts[3], &units.Hour) {
  82. return units, err
  83. }
  84. if !parse("Minute", parts[4], &units.Minute) {
  85. return units, err
  86. }
  87. if !parse("Second", parts[5], &units.Second) {
  88. return units, err
  89. }
  90. if !parse("Millisecond", parts[6], &units.Millisecond) {
  91. return units, err
  92. }
  93. if !parse("Microsecond", parts[7], &units.Microsecond) {
  94. return units, err
  95. }
  96. return units, err
  97. }