1
0

date_counter.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Copyright 2017 fatedier, fatedier@gmail.com
  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 metric
  15. import (
  16. "sync"
  17. "time"
  18. )
  19. type DateCounter interface {
  20. TodayCount() int64
  21. GetLastDaysCount(lastdays int64) []int64
  22. Inc(int64)
  23. Dec(int64)
  24. Snapshot() DateCounter
  25. Clear()
  26. }
  27. func NewDateCounter(reserveDays int64) DateCounter {
  28. if reserveDays <= 0 {
  29. reserveDays = 1
  30. }
  31. return newStandardDateCounter(reserveDays)
  32. }
  33. type StandardDateCounter struct {
  34. reserveDays int64
  35. counts []int64
  36. lastUpdateDate time.Time
  37. mu sync.Mutex
  38. }
  39. func newStandardDateCounter(reserveDays int64) *StandardDateCounter {
  40. now := time.Now()
  41. now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
  42. s := &StandardDateCounter{
  43. reserveDays: reserveDays,
  44. counts: make([]int64, reserveDays),
  45. lastUpdateDate: now,
  46. }
  47. return s
  48. }
  49. func (c *StandardDateCounter) TodayCount() int64 {
  50. c.mu.Lock()
  51. defer c.mu.Unlock()
  52. c.rotate(time.Now())
  53. return c.counts[0]
  54. }
  55. func (c *StandardDateCounter) GetLastDaysCount(lastdays int64) []int64 {
  56. if lastdays > c.reserveDays {
  57. lastdays = c.reserveDays
  58. }
  59. counts := make([]int64, lastdays)
  60. c.mu.Lock()
  61. defer c.mu.Unlock()
  62. c.rotate(time.Now())
  63. for i := 0; i < int(lastdays); i++ {
  64. counts[i] = c.counts[i]
  65. }
  66. return counts
  67. }
  68. func (c *StandardDateCounter) Inc(count int64) {
  69. c.mu.Lock()
  70. defer c.mu.Unlock()
  71. c.rotate(time.Now())
  72. c.counts[0] += count
  73. }
  74. func (c *StandardDateCounter) Dec(count int64) {
  75. c.mu.Lock()
  76. defer c.mu.Unlock()
  77. c.rotate(time.Now())
  78. c.counts[0] -= count
  79. }
  80. func (c *StandardDateCounter) Snapshot() DateCounter {
  81. c.mu.Lock()
  82. defer c.mu.Unlock()
  83. tmp := newStandardDateCounter(c.reserveDays)
  84. for i := 0; i < int(c.reserveDays); i++ {
  85. tmp.counts[i] = c.counts[i]
  86. }
  87. return tmp
  88. }
  89. func (c *StandardDateCounter) Clear() {
  90. c.mu.Lock()
  91. defer c.mu.Unlock()
  92. for i := 0; i < int(c.reserveDays); i++ {
  93. c.counts[i] = 0
  94. }
  95. }
  96. // rotate
  97. // Must hold the lock before calling this function.
  98. func (c *StandardDateCounter) rotate(now time.Time) {
  99. now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
  100. days := int(now.Sub(c.lastUpdateDate).Hours() / 24)
  101. defer func() {
  102. c.lastUpdateDate = now
  103. }()
  104. if days <= 0 {
  105. return
  106. } else if days >= int(c.reserveDays) {
  107. c.counts = make([]int64, c.reserveDays)
  108. return
  109. }
  110. newCounts := make([]int64, c.reserveDays)
  111. for i := days; i < int(c.reserveDays); i++ {
  112. newCounts[i] = c.counts[i-days]
  113. }
  114. c.counts = newCounts
  115. }