# HG changeset patch # User Sascha L. Teichmann # Date 1558362979 -7200 # Node ID c86a8e70b40f8968b1b092add9bd996b3c362752 # Parent 6172acfa7ff5f30ae97644048798f17469faccf1 Made time interpolation more precise and added a unit test. diff -r 6172acfa7ff5 -r c86a8e70b40f pkg/common/time.go --- a/pkg/common/time.go Mon May 20 16:28:57 2019 +0200 +++ b/pkg/common/time.go Mon May 20 16:36:19 2019 +0200 @@ -35,6 +35,8 @@ ValueAbove ValueRangeKind = +1 ) +var utc0 = time.Unix(0, 0) + func InterpolateValueByTime(t1 time.Time, m1 float64, t2 time.Time, m2 float64) func(time.Time) (float64, ValueRangeKind) { // f(t1) = m1 @@ -64,7 +66,7 @@ } a := (m1 - m2) / t1.Sub(t2).Seconds() - b := m1 - a*float64(t1.Unix()) + b := m1 - a*t1.Sub(utc0).Seconds() return func(t time.Time) (float64, ValueRangeKind) { switch { @@ -73,7 +75,7 @@ case t.After(max): return 0, ValueAbove default: - return a*float64(t.Unix()) + b, ValueInside + return a*t.Sub(utc0).Seconds() + b, ValueInside } } } @@ -104,7 +106,7 @@ min, max := math.Min(m1, m2), math.Max(m1, m2) a := t1.Sub(t2).Seconds() / (m1 - m2) - b := float64(t1.Unix()) - m1*a + b := t1.Sub(utc0).Seconds() - m1*a return func(m float64) (time.Time, ValueRangeKind) { switch { @@ -113,7 +115,10 @@ case m > max: return time.Time{}, ValueAbove default: - return time.Unix(int64(math.Ceil(m*a+b)), 0), ValueInside + x := m*a + b + secs := math.Ceil(x) + nsecs := math.Ceil((x - secs) * (999999999 + 1)) + return time.Unix(int64(secs), int64(nsecs)), ValueInside } } } diff -r 6172acfa7ff5 -r c86a8e70b40f pkg/common/time_test.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/common/time_test.go Mon May 20 16:36:19 2019 +0200 @@ -0,0 +1,61 @@ +// This is Free Software under GNU Affero General Public License v >= 3.0 +// without warranty, see README.md and license for details. +// +// SPDX-License-Identifier: AGPL-3.0-or-later +// License-Filename: LICENSES/AGPL-3.0.txt +// +// Copyright (C) 2018, 2019 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Sascha L. Teichmann + +package common + +import ( + "testing" + "time" +) + +func TestInterpolateTimeByValue(t *testing.T) { + + t1 := time.Now().UTC() + t2 := t1.Add(time.Hour).UTC() + + f := InterpolateTimeByValue(t1, 10, t2, 20) + + v1, _ := f(10) + v2, _ := f(20) + v3, _ := f(15) + + t3 := t1.Add(time.Hour / 2) + + d1 := v1.Sub(t1) + d2 := v2.Sub(t2) + d3 := v3.Sub(t3) + + if d1 < 0 { + d1 = -d1 + } + + if d1 > 100*time.Microsecond { + t.Errorf("difference too big t1: %v\n", d1) + } + + if d2 < 0 { + d2 = -d2 + } + + if d2 > 100*time.Microsecond { + t.Errorf("difference too big t2: %v\n", d2) + } + + if d3 < 0 { + d3 = -d3 + } + + if d3 > 100*time.Microsecond { + t.Errorf("difference too big t3: %v\n", d3) + } +}