diff --git a/julian/julian.go b/julian/julian.go index 2b16a7e..f5846e8 100644 --- a/julian/julian.go +++ b/julian/julian.go @@ -120,3 +120,26 @@ func JDateToTime(d Date) time.Time { d = dateDiff(d, offset) return time.Date(d.year, d.month, d.day, 0, 0, 0, 0, time.UTC) } + +func TimeToJDate(t time.Time) Date { + offset := -2 + // The date when the offset changes in the gregorian calendar is always + // 1st of March, so we can always just check the year, and see if we're + // past 1st of March year + year := t.Year() + if t.Month() < time.March { + year-- + } + + borderYear := 100 + for year >= borderYear { + if borderYear%400 != 0 { + offset++ + } + borderYear += 100 + } + + d := Date{t.Year(), t.Month(), t.Day()} + d = dateDiff(d, -offset) + return d +} diff --git a/julian/julian_test.go b/julian/julian_test.go index d70a4e2..e60a38e 100644 --- a/julian/julian_test.go +++ b/julian/julian_test.go @@ -145,3 +145,82 @@ func TestJDateToTime(t *testing.T) { }) } } + +func TestTimeToJDate(t *testing.T) { + gDate := func(year int, month time.Month, day int) time.Time { + return time.Date(year, month, day, 0, 0, 0, 0, time.UTC) + } + var tests = []struct { + gd time.Time + want Date + }{ + {gDate(100, time.February, 27), Date{100, time.February, 29}}, + {gDate(100, time.February, 28), Date{100, time.March, 1}}, + {gDate(100, time.March, 1), Date{100, time.March, 2}}, + {gDate(200, time.February, 27), Date{200, time.February, 28}}, + {gDate(200, time.February, 28), Date{200, time.February, 29}}, + {gDate(200, time.March, 1), Date{200, time.March, 1}}, + {gDate(300, time.February, 28), Date{300, time.February, 28}}, + {gDate(300, time.March, 1), Date{300, time.February, 29}}, + {gDate(300, time.March, 2), Date{300, time.March, 1}}, + {gDate(500, time.March, 1), Date{500, time.February, 28}}, + {gDate(500, time.March, 2), Date{500, time.February, 29}}, + {gDate(500, time.March, 3), Date{500, time.March, 1}}, + {gDate(600, time.March, 2), Date{600, time.February, 28}}, + {gDate(600, time.March, 3), Date{600, time.February, 29}}, + {gDate(600, time.March, 4), Date{600, time.March, 1}}, + {gDate(700, time.March, 3), Date{700, time.February, 28}}, + {gDate(700, time.March, 4), Date{700, time.February, 29}}, + {gDate(700, time.March, 5), Date{700, time.March, 1}}, + {gDate(900, time.March, 4), Date{900, time.February, 28}}, + {gDate(900, time.March, 5), Date{900, time.February, 29}}, + {gDate(900, time.March, 6), Date{900, time.March, 1}}, + {gDate(1000, time.March, 5), Date{1000, time.February, 28}}, + {gDate(1000, time.March, 6), Date{1000, time.February, 29}}, + {gDate(1000, time.March, 7), Date{1000, time.March, 1}}, + {gDate(1100, time.March, 6), Date{1100, time.February, 28}}, + {gDate(1100, time.March, 7), Date{1100, time.February, 29}}, + {gDate(1100, time.March, 8), Date{1100, time.March, 1}}, + {gDate(1300, time.March, 7), Date{1300, time.February, 28}}, + {gDate(1300, time.March, 8), Date{1300, time.February, 29}}, + {gDate(1300, time.March, 9), Date{1300, time.March, 1}}, + {gDate(1400, time.March, 8), Date{1400, time.February, 28}}, + {gDate(1400, time.March, 9), Date{1400, time.February, 29}}, + {gDate(1400, time.March, 10), Date{1400, time.March, 1}}, + {gDate(1500, time.March, 9), Date{1500, time.February, 28}}, + {gDate(1500, time.March, 10), Date{1500, time.February, 29}}, + {gDate(1500, time.March, 11), Date{1500, time.March, 1}}, + {gDate(1582, time.October, 14), Date{1582, time.October, 4}}, + {gDate(1582, time.October, 15), Date{1582, time.October, 5}}, + {gDate(1582, time.October, 16), Date{1582, time.October, 6}}, + {gDate(1700, time.February, 28), Date{1700, time.February, 18}}, + {gDate(1700, time.March, 1), Date{1700, time.February, 19}}, + {gDate(1700, time.March, 10), Date{1700, time.February, 28}}, + {gDate(1700, time.March, 11), Date{1700, time.February, 29}}, + {gDate(1700, time.March, 12), Date{1700, time.March, 1}}, + {gDate(1800, time.February, 28), Date{1800, time.February, 17}}, + {gDate(1800, time.March, 1), Date{1800, time.February, 18}}, + {gDate(1800, time.March, 11), Date{1800, time.February, 28}}, + {gDate(1800, time.March, 12), Date{1800, time.February, 29}}, + {gDate(1800, time.March, 13), Date{1800, time.March, 1}}, + {gDate(1900, time.February, 28), Date{1900, time.February, 16}}, + {gDate(1900, time.March, 1), Date{1900, time.February, 17}}, + {gDate(1900, time.March, 12), Date{1900, time.February, 28}}, + {gDate(1900, time.March, 13), Date{1900, time.February, 29}}, + {gDate(1900, time.March, 14), Date{1900, time.March, 1}}, + {gDate(2100, time.February, 28), Date{2100, time.February, 15}}, + {gDate(2100, time.March, 1), Date{2100, time.February, 16}}, + {gDate(2100, time.March, 13), Date{2100, time.February, 28}}, + {gDate(2100, time.March, 14), Date{2100, time.February, 29}}, + } + + for _, tt := range tests { + testname := fmt.Sprintf("%v, %v", tt.gd, tt.want) + t.Run(testname, func(t *testing.T) { + ans := TimeToJDate(tt.gd) + if ans != tt.want { + t.Errorf("got %v, want %v", ans, tt.want) + } + }) + } +}