Mercurial > gemma
comparison pkg/common/time.go @ 3332:c86a8e70b40f
Made time interpolation more precise and added a unit test.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 20 May 2019 16:36:19 +0200 |
parents | 8c4c1b3fd856 |
children | ecb4baa2be1a |
comparison
equal
deleted
inserted
replaced
3331:6172acfa7ff5 | 3332:c86a8e70b40f |
---|---|
33 ValueBelow ValueRangeKind = -1 | 33 ValueBelow ValueRangeKind = -1 |
34 ValueInside ValueRangeKind = 0 | 34 ValueInside ValueRangeKind = 0 |
35 ValueAbove ValueRangeKind = +1 | 35 ValueAbove ValueRangeKind = +1 |
36 ) | 36 ) |
37 | 37 |
38 var utc0 = time.Unix(0, 0) | |
39 | |
38 func InterpolateValueByTime(t1 time.Time, m1 float64, t2 time.Time, m2 float64) func(time.Time) (float64, ValueRangeKind) { | 40 func InterpolateValueByTime(t1 time.Time, m1 float64, t2 time.Time, m2 float64) func(time.Time) (float64, ValueRangeKind) { |
39 | 41 |
40 // f(t1) = m1 | 42 // f(t1) = m1 |
41 // f(t2) = m2 | 43 // f(t2) = m2 |
42 // m1 = t1*a + b <=> b = m1 - t1*a | 44 // m1 = t1*a + b <=> b = m1 - t1*a |
62 } else { | 64 } else { |
63 min, max = t2, t1 | 65 min, max = t2, t1 |
64 } | 66 } |
65 | 67 |
66 a := (m1 - m2) / t1.Sub(t2).Seconds() | 68 a := (m1 - m2) / t1.Sub(t2).Seconds() |
67 b := m1 - a*float64(t1.Unix()) | 69 b := m1 - a*t1.Sub(utc0).Seconds() |
68 | 70 |
69 return func(t time.Time) (float64, ValueRangeKind) { | 71 return func(t time.Time) (float64, ValueRangeKind) { |
70 switch { | 72 switch { |
71 case t.Before(min): | 73 case t.Before(min): |
72 return 0, ValueBelow | 74 return 0, ValueBelow |
73 case t.After(max): | 75 case t.After(max): |
74 return 0, ValueAbove | 76 return 0, ValueAbove |
75 default: | 77 default: |
76 return a*float64(t.Unix()) + b, ValueInside | 78 return a*t.Sub(utc0).Seconds() + b, ValueInside |
77 } | 79 } |
78 } | 80 } |
79 } | 81 } |
80 | 82 |
81 func InterpolateTimeByValue(t1 time.Time, m1 float64, t2 time.Time, m2 float64) func(float64) (time.Time, ValueRangeKind) { | 83 func InterpolateTimeByValue(t1 time.Time, m1 float64, t2 time.Time, m2 float64) func(float64) (time.Time, ValueRangeKind) { |
102 } | 104 } |
103 | 105 |
104 min, max := math.Min(m1, m2), math.Max(m1, m2) | 106 min, max := math.Min(m1, m2), math.Max(m1, m2) |
105 | 107 |
106 a := t1.Sub(t2).Seconds() / (m1 - m2) | 108 a := t1.Sub(t2).Seconds() / (m1 - m2) |
107 b := float64(t1.Unix()) - m1*a | 109 b := t1.Sub(utc0).Seconds() - m1*a |
108 | 110 |
109 return func(m float64) (time.Time, ValueRangeKind) { | 111 return func(m float64) (time.Time, ValueRangeKind) { |
110 switch { | 112 switch { |
111 case m < min: | 113 case m < min: |
112 return time.Time{}, ValueBelow | 114 return time.Time{}, ValueBelow |
113 case m > max: | 115 case m > max: |
114 return time.Time{}, ValueAbove | 116 return time.Time{}, ValueAbove |
115 default: | 117 default: |
116 return time.Unix(int64(math.Ceil(m*a+b)), 0), ValueInside | 118 x := m*a + b |
119 secs := math.Ceil(x) | |
120 nsecs := math.Ceil((x - secs) * (999999999 + 1)) | |
121 return time.Unix(int64(secs), int64(nsecs)), ValueInside | |
117 } | 122 } |
118 } | 123 } |
119 } | 124 } |