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.

58 lines
1.3 KiB

  1. package time
  2. import (
  3. "sort"
  4. "time"
  5. )
  6. // Now returns the current time in UTC with no monotonic component.
  7. func Now() time.Time {
  8. return Canonical(time.Now())
  9. }
  10. // Canonical returns UTC time with no monotonic component.
  11. // Stripping the monotonic component is for time equality.
  12. // See https://github.com/tendermint/tendermint/pull/2203#discussion_r215064334
  13. func Canonical(t time.Time) time.Time {
  14. return t.Round(0).UTC()
  15. }
  16. // WeightedTime for computing a median.
  17. type WeightedTime struct {
  18. Time time.Time
  19. Weight int64
  20. }
  21. // NewWeightedTime with time and weight.
  22. func NewWeightedTime(time time.Time, weight int64) *WeightedTime {
  23. return &WeightedTime{
  24. Time: time,
  25. Weight: weight,
  26. }
  27. }
  28. // WeightedMedian computes weighted median time for a given array of WeightedTime and the total voting power.
  29. func WeightedMedian(weightedTimes []*WeightedTime, totalVotingPower int64) (res time.Time) {
  30. median := totalVotingPower / 2
  31. sort.Slice(weightedTimes, func(i, j int) bool {
  32. if weightedTimes[i] == nil {
  33. return false
  34. }
  35. if weightedTimes[j] == nil {
  36. return true
  37. }
  38. return weightedTimes[i].Time.UnixNano() < weightedTimes[j].Time.UnixNano()
  39. })
  40. for _, weightedTime := range weightedTimes {
  41. if weightedTime != nil {
  42. if median <= weightedTime.Weight {
  43. res = weightedTime.Time
  44. break
  45. }
  46. median -= weightedTime.Weight
  47. }
  48. }
  49. return
  50. }