diff --git a/README.md b/README.md index 18d69a5..ffc21f8 100644 --- a/README.md +++ b/README.md @@ -263,7 +263,6 @@ func main() { ``` $ go run sample/sample4.go 2022-01-01 -$ go run sample/sample4.go 2022-01-01 Julian Day Number of 2022-01-01 is 2459580 ``` diff --git a/jdn/jdn.go b/jdn/jdn.go index 7a52722..03aec3e 100644 --- a/jdn/jdn.go +++ b/jdn/jdn.go @@ -5,19 +5,19 @@ import ( "time" ) -// GetJD returns Julian Day from time.Time. +// GetJD returns Julian Date from time.Time. func GetJD(dt time.Time) *big.Rat { dt = dt.In(time.UTC) y := intRat(int64(dt.Year())) m := int64(dt.Month()) d := int64(dt.Day()) k := floorRat(quoInt(intRat(14-m), 12)) - jdn := floorRat(mulRat(addInt(subRat(y, k), 4800), fracInt(1461, 4))) - jdn = addRat(jdn, floorRat(mulRat(addInt(mulInt(k, 12), m-2), fracInt(367, 12)))) - jdn = subRat(jdn, floorRat(mulRat(floorRat(quoInt(addInt(subRat(y, k), 4900), 100)), fracInt(3, 4)))) - jdn = addInt(jdn, d-32075) - jdn = addRat(jdn, subRat(quoRat(addRat(intRat(int64(dt.Second()+dt.Minute()*60+dt.Hour()*3600)), fracInt(int64(dt.Nanosecond()), 999999999)), floatRat((24*time.Hour).Seconds())), floatRat(0.5))) - return jdn + j := floorRat(mulRat(addInt(subRat(y, k), 4800), fracInt(1461, 4))) + j = addRat(j, floorRat(mulRat(addInt(mulInt(k, 12), m-2), fracInt(367, 12)))) + j = subRat(j, floorRat(mulRat(floorRat(quoInt(addInt(subRat(y, k), 4900), 100)), fracInt(3, 4)))) + j = addInt(j, d-32075) + j = addRat(j, subRat(quoRat(addRat(intRat(int64(dt.Second()+dt.Minute()*60+dt.Hour()*3600)), fracInt(int64(dt.Nanosecond()), 999999999)), floatRat((24*time.Hour).Seconds())), floatRat(0.5))) + return j } // GetJDN returns Julian Day Number from time.Time. @@ -25,7 +25,7 @@ func GetJDN(dt time.Time) int64 { return floorRat(GetJD(dt)).Num().Int64() } -// GetMJD returns Modified Julian Day from time.Time. +// GetMJD returns Modified Julian Date from time.Time. func GetMJD(dt time.Time) *big.Rat { return subRat(GetJD(dt), floatRat(2400000.5)) } @@ -35,6 +35,21 @@ func GetMJDN(dt time.Time) int64 { return floorRat(GetMJD(dt)).Num().Int64() } +// FromJDN returns time.Time instance form Julian Day Number. +func FromJD(jn int64) time.Time { + l := intRat(jn + 68569) + n := floorRat(mulInt(quoInt(l, 146097), 4)) + l = subRat(l, floorRat(quoInt(addInt(mulInt(n, 146097), 3), 4))) + i := floorRat(quoInt(mulInt(addInt(l, 1), 4000), 1461001)) + l = addInt(subRat(l, floorRat(quoInt(mulInt(i, 1461), 4))), 31) + j := floorRat(quoInt(mulInt(l, 80), 2447)) + day := subRat(l, floorRat(quoInt(mulInt(j, 2447), 80))) + l = floorRat(quoInt(j, 11)) + month := subRat(addInt(j, 2), mulInt(l, 12)) + year := addRat(mulInt(addInt(n, -49), 100), addRat(i, l)) + return time.Date(int(year.Num().Int64()), time.Month(int(month.Num().Int64())), int(day.Num().Int64()), 12, 0, 0, 0, time.UTC) +} + func intRat(x int64) *big.Rat { return fracInt(x, 1) } diff --git a/jdn/jdn_test.go b/jdn/jdn_test.go index 5ca380c..4e9257b 100644 --- a/jdn/jdn_test.go +++ b/jdn/jdn_test.go @@ -9,23 +9,28 @@ import ( func TestGetJDN(t *testing.T) { jst := time.FixedZone("JST", int((9 * time.Hour).Seconds())) // Japan standard Time testCases := []struct { - inp time.Time - outp1 *big.Rat - outp2 int64 - outp3 *big.Rat - outp4 int64 + inp time.Time + outp1 *big.Rat + outp2 int64 + outpDt time.Time + outp3 *big.Rat + outp4 int64 }{ - {inp: time.Date(2015, time.January, 1, 0, 0, 0, 0, time.UTC), outp1: floatRat(2457023.5), outp2: 2457023, outp3: floatRat(57023.0), outp4: 57023}, - {inp: time.Date(2022, time.January, 1, 0, 0, 0, 0, jst), outp1: floatRat(2459580.125), outp2: 2459580, outp3: floatRat(59579.625), outp4: 59579}, + {inp: time.Date(2015, time.January, 1, 0, 0, 0, 0, time.UTC), outp1: floatRat(2457023.5), outp2: 2457023, outpDt: time.Date(2015, time.January, 0, 12, 0, 0, 0, time.UTC), outp3: floatRat(57023.0), outp4: 57023}, + {inp: time.Date(2022, time.January, 1, 0, 0, 0, 0, jst), outp1: floatRat(2459580.125), outp2: 2459580, outpDt: time.Date(2022, time.January, 0, 12, 0, 0, 0, time.UTC), outp3: floatRat(59579.625), outp4: 59579}, } for _, tc := range testCases { jd := GetJD(tc.inp) if jd.Cmp(tc.outp1) != 0 { t.Errorf("GetJD(%v) is %v, want %v.", tc.inp, jd.FloatString(5), tc.outp1.FloatString(5)) } - jdn := GetJDN(tc.inp) - if jdn != tc.outp2 { - t.Errorf("GetJDN(%v) is %v, want %v.", tc.inp, jdn, tc.outp2) + jn := GetJDN(tc.inp) + if jn != tc.outp2 { + t.Errorf("GetJDN(%v) is %v, want %v.", tc.inp, jn, tc.outp2) + } + dt := FromJD(jn) + if !dt.Equal(tc.outpDt) { + t.Errorf("FromJD(%v) is %v, want %v.", jn, dt, tc.outpDt) } mjd := GetMJD(tc.inp) if mjd.Cmp(tc.outp3) != 0 {