-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjuliandays.go
111 lines (91 loc) · 2.39 KB
/
juliandays.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package juliandays
import (
"errors"
"math"
"time"
)
var (
startOfJulian = time.Date(-4712, 1, 1, 12, 0, 0, 0, time.UTC)
endOfJulian = time.Date(1582, 10, 4, 23, 59, 59, 0, time.UTC)
startOfGregorian = time.Date(1582, 10, 15, 0, 0, 0, 0, time.UTC)
)
// FromTime converts Golang std time into Julian Days.
func FromTime(dt time.Time) (float64, error) {
// Convert to UTC
dt = dt.UTC()
// If dt is before Julian calendar, stop
if dt.Before(startOfJulian) {
return 0, errors.New("year is before Julian calendar")
}
// If date is in blank days, stop
if dt.After(endOfJulian) && dt.Before(startOfGregorian) {
return 0, errors.New("date is within blank days")
}
// Prepare variables for calculating
Y := float64(dt.Year())
M := float64(dt.Month())
D := float64(dt.Day())
H := float64(dt.Hour())
m := float64(dt.Minute())
s := float64(dt.Second())
// If month <= 2, change year and month
if M <= 2 {
M += 12
Y--
}
// Check whether date is gregorian or julian
var constant float64
if dt.After(endOfJulian) {
temp := math.Floor(float64(Y) / 100)
constant = 2 + math.Floor(temp/4) - temp
}
// Calculate julian day
yearToDays := math.Floor(Y * 365.25)
monthToDays := math.Floor((M + 1) * 30.6001)
timeToDays := (H*3600 + m*60 + s) / 86400
julianDay := 1720994.5 + yearToDays + monthToDays + constant + D + timeToDays
return julianDay, nil
}
// ToTime converts Julian Days into Golang std time.
func ToTime(jd float64) time.Time {
// Prepare variables for calculating
jd1 := jd + 0.5
z := math.Floor(jd1)
f := jd1 - z
a := z
if z >= 2299161 {
aa := math.Floor((z - 1867216.25) / 36524.25)
a = z + 1 + aa - math.Floor(aa/4)
}
b := a + 1524
c := math.Floor((b - 122.1) / 365.25)
d := math.Floor(c * 365.25)
e := math.Floor((b - d) / 30.6001)
// Calculate day with its time
dayTime := b - d - math.Floor(e*30.6001) + f
day := math.Floor(dayTime)
// Calculate time
seconds := (dayTime - day) * 24 * 60 * 60
hours := math.Floor(seconds / 3600)
seconds -= hours * 3600
minutes := math.Floor(seconds / 60)
seconds -= minutes * 60
// Calculate month
var month float64
if e < 14 {
month = e - 1
} else {
month = e - 13
}
// Calculate year
var year float64
if month > 2 {
year = c - 4716
} else {
year = c - 4715
}
// Create date
return time.Date(
int(year), time.Month(int(month)), int(day),
int(hours), int(minutes), int(seconds), 0, time.UTC)
}