bug fix && moon phase date calc
This commit is contained in:
parent
b4b2cea738
commit
9b50cfff3f
@ -207,13 +207,13 @@ func JDE2DateByZone(JD float64, tz *time.Location, byZone bool) time.Time {
|
|||||||
return time.Unix(dates.Unix()+int64(tms), int64((tms-math.Floor(tms))*1000000000))
|
return time.Unix(dates.Unix()+int64(tms), int64((tms-math.Floor(tms))*1000000000))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLunar(year, month, day int) (lmonth, lday int, leap bool, result string) {
|
func GetLunar(year, month, day int, tz float64) (lmonth, lday int, leap bool, result string) {
|
||||||
jde := JDECalc(year, month, float64(day)) //计算当前JDE时间
|
jde := JDECalc(year, month, float64(day)) //计算当前JDE时间
|
||||||
if month == 11 || month == 12 { //判断当前日期属于前一年周期还是后一年周期
|
if month == 11 || month == 12 { //判断当前日期属于前一年周期还是后一年周期
|
||||||
//判断方法:当前日期与冬至日所在朔望月的关系
|
//判断方法:当前日期与冬至日所在朔望月的关系
|
||||||
winterday := GetJQTime(year, 270) + 8.0/24.0 //冬至日日期(世界时,北京时间)
|
winterday := GetJQTime(year, 270) + tz //冬至日日期(世界时,北京时间)
|
||||||
Fday := TD2UT(CalcMoonS(float64(year)+11.0/12.0+5.0/30.0/12.0, 0), true) + 8.0/24.0 //朔月(世界时,北京时间)
|
Fday := TD2UT(CalcMoonS(float64(year)+11.0/12.0+5.0/30.0/12.0, 0), true) + tz //朔月(世界时,北京时间)
|
||||||
Yday := TD2UT(CalcMoonS(float64(year)+1.0, 0), true) + 8.0/24.0 //下一朔月(世界时,北京时间)
|
Yday := TD2UT(CalcMoonS(float64(year)+1.0, 0), true) + tz //下一朔月(世界时,北京时间)
|
||||||
if Fday-math.Floor(Fday) > 0.5 {
|
if Fday-math.Floor(Fday) > 0.5 {
|
||||||
Fday = math.Floor(Fday) + 0.5
|
Fday = math.Floor(Fday) + 0.5
|
||||||
} else {
|
} else {
|
||||||
@ -238,6 +238,9 @@ func GetLunar(year, month, day int) (lmonth, lday int, leap bool, result string)
|
|||||||
winter1 := jieqi[1] //第一年冬至日
|
winter1 := jieqi[1] //第一年冬至日
|
||||||
winter2 := jieqi[25] //第二年冬至日
|
winter2 := jieqi[25] //第二年冬至日
|
||||||
for k, v := range moon {
|
for k, v := range moon {
|
||||||
|
if tz != 8.0/24 {
|
||||||
|
v = v - 8.0/24 + tz
|
||||||
|
}
|
||||||
if v-math.Floor(v) > 0.5 {
|
if v-math.Floor(v) > 0.5 {
|
||||||
moon[k] = math.Floor(v) + 0.5
|
moon[k] = math.Floor(v) + 0.5
|
||||||
} else {
|
} else {
|
||||||
@ -245,6 +248,9 @@ func GetLunar(year, month, day int) (lmonth, lday int, leap bool, result string)
|
|||||||
}
|
}
|
||||||
} //置闰月为0点
|
} //置闰月为0点
|
||||||
for k, v := range jieqi {
|
for k, v := range jieqi {
|
||||||
|
if tz != 8.0/24 {
|
||||||
|
v = v - 8.0/24 + tz
|
||||||
|
}
|
||||||
if v-math.Floor(v) > 0.5 {
|
if v-math.Floor(v) > 0.5 {
|
||||||
jieqi[k] = math.Floor(v) + 0.5
|
jieqi[k] = math.Floor(v) + 0.5
|
||||||
} else {
|
} else {
|
||||||
@ -298,6 +304,9 @@ func GetLunar(year, month, day int) (lmonth, lday int, leap bool, result string)
|
|||||||
if sleap {
|
if sleap {
|
||||||
lmonth--
|
lmonth--
|
||||||
}
|
}
|
||||||
|
if lmonth <= 0 {
|
||||||
|
lmonth += 12
|
||||||
|
}
|
||||||
lday = int(jde-moon[i-1]) + 1
|
lday = int(jde-moon[i-1]) + 1
|
||||||
strmonth := []string{"十", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"}
|
strmonth := []string{"十", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"}
|
||||||
strday := []string{"初", "十", "廿", "三"}
|
strday := []string{"初", "十", "廿", "三"}
|
||||||
@ -319,7 +328,7 @@ func GetLunar(year, month, day int) (lmonth, lday int, leap bool, result string)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSolar(year, month, day int, leap bool) float64 {
|
func GetSolar(year, month, day int, leap bool, tz float64) float64 {
|
||||||
if month < 11 {
|
if month < 11 {
|
||||||
year--
|
year--
|
||||||
}
|
}
|
||||||
@ -328,6 +337,9 @@ func GetSolar(year, month, day int, leap bool) float64 {
|
|||||||
winter1 := jieqi[1] //第一年冬至日
|
winter1 := jieqi[1] //第一年冬至日
|
||||||
winter2 := jieqi[25] //第二年冬至日
|
winter2 := jieqi[25] //第二年冬至日
|
||||||
for k, v := range moon {
|
for k, v := range moon {
|
||||||
|
if tz != 8.0/24 {
|
||||||
|
v = v - 8.0/24 + tz
|
||||||
|
}
|
||||||
if v-math.Floor(v) > 0.5 {
|
if v-math.Floor(v) > 0.5 {
|
||||||
moon[k] = math.Floor(v) + 0.5
|
moon[k] = math.Floor(v) + 0.5
|
||||||
} else {
|
} else {
|
||||||
@ -335,6 +347,9 @@ func GetSolar(year, month, day int, leap bool) float64 {
|
|||||||
}
|
}
|
||||||
} //置闰月为0点
|
} //置闰月为0点
|
||||||
for k, v := range jieqi {
|
for k, v := range jieqi {
|
||||||
|
if tz != 8.0/24 {
|
||||||
|
v = v - 8.0/24 + tz
|
||||||
|
}
|
||||||
if v-math.Floor(v) > 0.5 {
|
if v-math.Floor(v) > 0.5 {
|
||||||
jieqi[k] = math.Floor(v) + 0.5
|
jieqi[k] = math.Floor(v) + 0.5
|
||||||
} else {
|
} else {
|
||||||
@ -354,6 +369,17 @@ func GetSolar(year, month, day int, leap bool) float64 {
|
|||||||
mooncount++
|
mooncount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
leapmonth := 20
|
||||||
|
if mooncount == 13 { //存在闰月
|
||||||
|
j, i := 3, 1
|
||||||
|
for i = min; i <= max; i++ {
|
||||||
|
if !(moon[i] <= jieqi[j] && moon[i+1] > jieqi[j]) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
j += 2
|
||||||
|
}
|
||||||
|
leapmonth = i - min + 1
|
||||||
|
}
|
||||||
if leap {
|
if leap {
|
||||||
month++
|
month++
|
||||||
}
|
}
|
||||||
@ -362,6 +388,9 @@ func GetSolar(year, month, day int, leap bool) float64 {
|
|||||||
} else {
|
} else {
|
||||||
month++
|
month++
|
||||||
}
|
}
|
||||||
|
if month >= leapmonth && !leap {
|
||||||
|
month++
|
||||||
|
}
|
||||||
jde := moon[min-1+month] + float64(day) - 1
|
jde := moon[min-1+month] + float64(day) - 1
|
||||||
return jde
|
return jde
|
||||||
}
|
}
|
||||||
|
@ -1106,36 +1106,40 @@ func MoonLight(JD float64) float64 {
|
|||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
|
||||||
func SunMoonSeek(JDE float64) float64 {
|
func SunMoonSeek(JDE float64, degree float64) float64 {
|
||||||
p := HMoonSeeLo(JDE) - (HSunSeeLo(JDE))
|
p := HMoonSeeLo(JDE) - (HSunSeeLo(JDE)) - degree
|
||||||
if p > 240 {
|
for p < -180 {
|
||||||
p -= 360
|
|
||||||
}
|
|
||||||
if p < -240 {
|
|
||||||
p += 360
|
p += 360
|
||||||
}
|
}
|
||||||
|
for p > 180 {
|
||||||
|
p -= 360
|
||||||
|
}
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CalcMoonSHByJDE(JDE float64, C int) float64 {
|
||||||
|
C = C * 180
|
||||||
|
JD1 := JDE
|
||||||
|
for {
|
||||||
|
JD0 := JD1
|
||||||
|
stDegree := SunMoonSeek(JD0, float64(C))
|
||||||
|
stDegreep := (SunMoonSeek(JD0+0.000005, float64(C)) - SunMoonSeek(JD0-0.000005, float64(C))) / 0.00001
|
||||||
|
JD1 = JD0 - stDegree/stDegreep
|
||||||
|
if math.Abs(JD1-JD0) <= 0.00001 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JD1
|
||||||
|
}
|
||||||
|
|
||||||
func CalcMoonSH(Year float64, C int) float64 {
|
func CalcMoonSH(Year float64, C int) float64 {
|
||||||
JDE := CalcMoonS(Year, C)
|
JDE := CalcMoonS(Year, C)
|
||||||
C = C * 180
|
C = C * 180
|
||||||
i := 0
|
|
||||||
for {
|
|
||||||
JDE -= 0.005
|
|
||||||
i++
|
|
||||||
if i > 1000 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if SunMoonSeek(JDE) <= float64(C) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JD1 := JDE
|
JD1 := JDE
|
||||||
for {
|
for {
|
||||||
JD0 := JD1
|
JD0 := JD1
|
||||||
stDegree := SunMoonSeek(JD0) - float64(C)
|
stDegree := SunMoonSeek(JD0, float64(C))
|
||||||
stDegreep := (SunMoonSeek(JD0+0.000005) - SunMoonSeek(JD0-0.000005)) / 0.00001
|
stDegreep := (SunMoonSeek(JD0+0.000005, float64(C)) - SunMoonSeek(JD0-0.000005, float64(C))) / 0.00001
|
||||||
JD1 = JD0 - stDegree/stDegreep
|
JD1 = JD0 - stDegree/stDegreep
|
||||||
if math.Abs(JD1-JD0) <= 0.00001 {
|
if math.Abs(JD1-JD0) <= 0.00001 {
|
||||||
break
|
break
|
||||||
@ -1196,6 +1200,25 @@ func CalcMoonS(Year float64, C int) float64 {
|
|||||||
return JDE
|
return JDE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CalcMoonXHByJDE(JDE float64, C int) float64 {
|
||||||
|
if C == 0 {
|
||||||
|
C = 90
|
||||||
|
} else {
|
||||||
|
C = -90
|
||||||
|
}
|
||||||
|
JD1 := JDE
|
||||||
|
for {
|
||||||
|
JD0 := JD1
|
||||||
|
stDegree := SunMoonSeek(JD0, float64(C))
|
||||||
|
stDegreep := (SunMoonSeek(JD0+0.000005, float64(C)) - SunMoonSeek(JD0-0.000005, float64(C))) / 0.00001
|
||||||
|
JD1 = JD0 - stDegree/stDegreep
|
||||||
|
if math.Abs(JD1-JD0) <= 0.00001 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JD1
|
||||||
|
}
|
||||||
|
|
||||||
func CalcMoonXH(Year float64, C int) float64 {
|
func CalcMoonXH(Year float64, C int) float64 {
|
||||||
JDE := CalcMoonX(Year, C)
|
JDE := CalcMoonX(Year, C)
|
||||||
if C == 0 {
|
if C == 0 {
|
||||||
@ -1203,22 +1226,11 @@ func CalcMoonXH(Year float64, C int) float64 {
|
|||||||
} else {
|
} else {
|
||||||
C = -90
|
C = -90
|
||||||
}
|
}
|
||||||
i := 0
|
|
||||||
for {
|
|
||||||
JDE -= 0.005
|
|
||||||
i++
|
|
||||||
if i > 1000 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if SunMoonSeek(JDE) <= float64(C) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JD1 := JDE
|
JD1 := JDE
|
||||||
for {
|
for {
|
||||||
JD0 := JD1
|
JD0 := JD1
|
||||||
stDegree := SunMoonSeek(JD0) - float64(C)
|
stDegree := SunMoonSeek(JD0, float64(C))
|
||||||
stDegreep := (SunMoonSeek(JD0+0.000005) - SunMoonSeek(JD0-0.000005)) / 0.00001
|
stDegreep := (SunMoonSeek(JD0+0.000005, float64(C)) - SunMoonSeek(JD0-0.000005, float64(C))) / 0.00001
|
||||||
JD1 = JD0 - stDegree/stDegreep
|
JD1 = JD0 - stDegree/stDegreep
|
||||||
if math.Abs(JD1-JD0) <= 0.00001 {
|
if math.Abs(JD1-JD0) <= 0.00001 {
|
||||||
break
|
break
|
||||||
|
@ -37,7 +37,7 @@ const (
|
|||||||
// 传入 公历年月日
|
// 传入 公历年月日
|
||||||
// 返回 农历月,日,是否闰月以及文字描述
|
// 返回 农历月,日,是否闰月以及文字描述
|
||||||
func Lunar(year, month, day int) (int, int, bool, string) {
|
func Lunar(year, month, day int) (int, int, bool, string) {
|
||||||
return basic.GetLunar(year, month, day)
|
return basic.GetLunar(year, month, day, 8.0/24.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChineseLunar 公历转农历
|
// ChineseLunar 公历转农历
|
||||||
@ -45,7 +45,7 @@ func Lunar(year, month, day int) (int, int, bool, string) {
|
|||||||
// 返回 农历月,日,是否闰月以及文字描述
|
// 返回 农历月,日,是否闰月以及文字描述
|
||||||
// 忽略时区,日期一律按北京时间计算
|
// 忽略时区,日期一律按北京时间计算
|
||||||
func ChineseLunar(date time.Time) (int, int, bool, string) {
|
func ChineseLunar(date time.Time) (int, int, bool, string) {
|
||||||
return basic.GetLunar(date.Year(), int(date.Month()), date.Day())
|
return basic.GetLunar(date.Year(), int(date.Month()), date.Day(), 8.0/24.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Solar 农历转公历
|
// Solar 农历转公历
|
||||||
@ -55,7 +55,7 @@ func ChineseLunar(date time.Time) (int, int, bool, string) {
|
|||||||
// 例:计算己亥猪年腊月三十日对应的公历(即2020年1月24日)
|
// 例:计算己亥猪年腊月三十日对应的公历(即2020年1月24日)
|
||||||
// 由于农历还未到鼠年,故应当传入Solar(2019,12,30,false)
|
// 由于农历还未到鼠年,故应当传入Solar(2019,12,30,false)
|
||||||
func Solar(year, month, day int, leap bool) time.Time {
|
func Solar(year, month, day int, leap bool) time.Time {
|
||||||
jde := basic.GetSolar(year, month, day, leap)
|
jde := basic.GetSolar(year, month, day, leap, 8.0/24.0)
|
||||||
zone := time.FixedZone("CST", 8*3600)
|
zone := time.FixedZone("CST", 8*3600)
|
||||||
return basic.JDE2DateByZone(jde, zone, true)
|
return basic.JDE2DateByZone(jde, zone, true)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,50 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Solar(t *testing.T) {
|
type LunarSolar struct {
|
||||||
fmt.Println(Solar(2021, 1, 1, false))
|
Lyear int
|
||||||
fmt.Println(Solar(2020, 1, 1, false))
|
Lmonth int
|
||||||
|
Lday int
|
||||||
|
Leap bool
|
||||||
|
Year int
|
||||||
|
Month int
|
||||||
|
Day int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_ChineseCalendar(t *testing.T) {
|
||||||
|
var testData = []LunarSolar{
|
||||||
|
{Lyear: 2034, Lmonth: 1, Lday: 1, Leap: false, Year: 2034, Month: 2, Day: 19},
|
||||||
|
{Lyear: 2033, Lmonth: 12, Lday: 30, Leap: false, Year: 2034, Month: 2, Day: 18},
|
||||||
|
{Lyear: 2033, Lmonth: 11, Lday: 27, Leap: true, Year: 2034, Month: 1, Day: 17},
|
||||||
|
{Lyear: 2033, Lmonth: 11, Lday: 1, Leap: true, Year: 2033, Month: 12, Day: 22},
|
||||||
|
{Lyear: 2033, Lmonth: 11, Lday: 30, Leap: false, Year: 2033, Month: 12, Day: 21},
|
||||||
|
{Lyear: 2023, Lmonth: 2, Lday: 30, Leap: false, Year: 2023, Month: 3, Day: 21},
|
||||||
|
{Lyear: 2023, Lmonth: 2, Lday: 1, Leap: true, Year: 2023, Month: 3, Day: 22},
|
||||||
|
{Lyear: 2020, Lmonth: 1, Lday: 1, Leap: false, Year: 2020, Month: 1, Day: 25},
|
||||||
|
{Lyear: 2015, Lmonth: 1, Lday: 1, Leap: false, Year: 2015, Month: 2, Day: 19},
|
||||||
|
{Lyear: 2014, Lmonth: 12, Lday: 30, Leap: false, Year: 2015, Month: 2, Day: 18},
|
||||||
|
{Lyear: 1996, Lmonth: 1, Lday: 1, Leap: false, Year: 1996, Month: 2, Day: 19},
|
||||||
|
{Lyear: 1995, Lmonth: 12, Lday: 30, Leap: false, Year: 1996, Month: 2, Day: 18},
|
||||||
|
{Lyear: 1996, Lmonth: 10, Lday: 30, Leap: false, Year: 1996, Month: 12, Day: 10},
|
||||||
|
{Lyear: 2014, Lmonth: 9, Lday: 1, Leap: true, Year: 2014, Month: 10, Day: 24},
|
||||||
|
{Lyear: 2014, Lmonth: 9, Lday: 30, Leap: false, Year: 2014, Month: 10, Day: 23},
|
||||||
|
{Lyear: 2014, Lmonth: 10, Lday: 1, Leap: false, Year: 2014, Month: 11, Day: 22},
|
||||||
|
{Lyear: 2021, Lmonth: 12, Lday: 29, Leap: false, Year: 2022, Month: 1, Day: 31},
|
||||||
|
}
|
||||||
|
for _, v := range testData {
|
||||||
|
var lyear int = v.Year
|
||||||
|
lmonth, lday, leap, desp := Lunar(v.Year, v.Month, v.Day)
|
||||||
|
if lmonth > v.Month {
|
||||||
|
lyear--
|
||||||
|
}
|
||||||
|
fmt.Println(lyear, desp, v.Year, v.Month, v.Day)
|
||||||
|
if lyear != v.Lyear || lmonth != v.Lmonth || lday != v.Lday || leap != v.Leap {
|
||||||
|
t.Fatal(v, lyear, lmonth, lday, leap, desp)
|
||||||
|
}
|
||||||
|
|
||||||
|
date := Solar(v.Lyear, v.Lmonth, v.Lday, v.Leap)
|
||||||
|
if date.Year() != v.Year || int(date.Month()) != v.Month || date.Day() != v.Day {
|
||||||
|
t.Fatal(v, date)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
114
moon/moon.go
114
moon/moon.go
@ -2,6 +2,7 @@ package moon
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"math"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"b612.me/astro/basic"
|
"b612.me/astro/basic"
|
||||||
@ -180,24 +181,137 @@ func ShuoYue(year float64) time.Time {
|
|||||||
return basic.JDE2DateByZone(jde, time.UTC, false)
|
return basic.JDE2DateByZone(jde, time.UTC, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NextShuoYue(date time.Time) time.Time {
|
||||||
|
return nextMoonPhase(date, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LastShuoYue(date time.Time) time.Time {
|
||||||
|
return lastMoonPhase(date, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClosestShuoYue(date time.Time) time.Time {
|
||||||
|
return closestMoonPhase(date, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func closestMoonPhase(date time.Time, typed int) time.Time {
|
||||||
|
//0=shuo 1=wang 2=shangxian 3=xiaxian
|
||||||
|
jde := basic.TD2UT(basic.Date2JDE(date.UTC()), true)
|
||||||
|
if typed < 2 {
|
||||||
|
return basic.JDE2DateByZone(basic.TD2UT(basic.CalcMoonSHByJDE(jde, typed), false), date.Location(), false)
|
||||||
|
}
|
||||||
|
return basic.JDE2DateByZone(basic.TD2UT(basic.CalcMoonXHByJDE(jde, typed-2), false), date.Location(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nextMoonPhase(date time.Time, typed int) time.Time {
|
||||||
|
//0=shuo 1=wang 2=shangxian 3=xiaxian
|
||||||
|
diffCode := 0.00
|
||||||
|
switch typed {
|
||||||
|
case 1:
|
||||||
|
diffCode = 180
|
||||||
|
case 2:
|
||||||
|
diffCode = 90
|
||||||
|
case 3:
|
||||||
|
diffCode = 270
|
||||||
|
}
|
||||||
|
jde := basic.TD2UT(basic.Date2JDE(date.UTC()), true)
|
||||||
|
cost := basic.HMoonSeeLo(jde) - basic.HSunSeeLo(jde) - float64(diffCode)
|
||||||
|
for cost < 0 {
|
||||||
|
cost += 360
|
||||||
|
}
|
||||||
|
if cost < 0 && math.Floor(math.Abs(cost)*10000) == 0 {
|
||||||
|
cost = 0
|
||||||
|
}
|
||||||
|
if cost < 240 {
|
||||||
|
jde += (240 - cost) / 11.19
|
||||||
|
}
|
||||||
|
if typed < 2 {
|
||||||
|
return basic.JDE2DateByZone(basic.TD2UT(basic.CalcMoonSHByJDE(jde, typed), false), date.Location(), false)
|
||||||
|
}
|
||||||
|
return basic.JDE2DateByZone(basic.TD2UT(basic.CalcMoonXHByJDE(jde, typed-2), false), date.Location(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func lastMoonPhase(date time.Time, typed int) time.Time {
|
||||||
|
//0=shuo 1=wang 2=shangxian 3=xiaxian
|
||||||
|
diffCode := 0.00
|
||||||
|
switch typed {
|
||||||
|
case 1:
|
||||||
|
diffCode = 180
|
||||||
|
case 2:
|
||||||
|
diffCode = 90
|
||||||
|
case 3:
|
||||||
|
diffCode = 270
|
||||||
|
}
|
||||||
|
jde := basic.TD2UT(basic.Date2JDE(date.UTC()), true)
|
||||||
|
cost := basic.HMoonSeeLo(jde) - basic.HSunSeeLo(jde) - float64(diffCode)
|
||||||
|
for cost < 0 {
|
||||||
|
cost += 360
|
||||||
|
}
|
||||||
|
if cost > 0 && math.Floor(math.Abs(cost)*10000) == 0 {
|
||||||
|
cost = 360
|
||||||
|
}
|
||||||
|
if cost > 120 {
|
||||||
|
jde -= (cost - 120) / 11.19
|
||||||
|
}
|
||||||
|
if typed < 2 {
|
||||||
|
return basic.JDE2DateByZone(basic.TD2UT(basic.CalcMoonSHByJDE(jde, typed), false), date.Location(), false)
|
||||||
|
}
|
||||||
|
return basic.JDE2DateByZone(basic.TD2UT(basic.CalcMoonXHByJDE(jde, typed-2), false), date.Location(), false)
|
||||||
|
}
|
||||||
|
|
||||||
// WangYue 望月
|
// WangYue 望月
|
||||||
func WangYue(year float64) time.Time {
|
func WangYue(year float64) time.Time {
|
||||||
jde := basic.TD2UT(basic.CalcMoonSH(year, 1), false)
|
jde := basic.TD2UT(basic.CalcMoonSH(year, 1), false)
|
||||||
return basic.JDE2DateByZone(jde, time.UTC, false)
|
return basic.JDE2DateByZone(jde, time.UTC, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NextWangYue(date time.Time) time.Time {
|
||||||
|
return nextMoonPhase(date, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LastWangYue(date time.Time) time.Time {
|
||||||
|
return lastMoonPhase(date, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClosestWangYue(date time.Time) time.Time {
|
||||||
|
return closestMoonPhase(date, 1)
|
||||||
|
}
|
||||||
|
|
||||||
// ShangXianYue 上弦月
|
// ShangXianYue 上弦月
|
||||||
func ShangXianYue(year float64) time.Time {
|
func ShangXianYue(year float64) time.Time {
|
||||||
jde := basic.TD2UT(basic.CalcMoonXH(year, 0), false)
|
jde := basic.TD2UT(basic.CalcMoonXH(year, 0), false)
|
||||||
return basic.JDE2DateByZone(jde, time.UTC, false)
|
return basic.JDE2DateByZone(jde, time.UTC, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NextShangXianYue(date time.Time) time.Time {
|
||||||
|
return nextMoonPhase(date, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LastShangXianYue(date time.Time) time.Time {
|
||||||
|
return lastMoonPhase(date, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClosestShangXianYue(date time.Time) time.Time {
|
||||||
|
return closestMoonPhase(date, 2)
|
||||||
|
}
|
||||||
|
|
||||||
// XiaXianYue 下弦月
|
// XiaXianYue 下弦月
|
||||||
func XiaXianYue(year float64) time.Time {
|
func XiaXianYue(year float64) time.Time {
|
||||||
jde := basic.TD2UT(basic.CalcMoonXH(year, 1), false)
|
jde := basic.TD2UT(basic.CalcMoonXH(year, 1), false)
|
||||||
return basic.JDE2DateByZone(jde, time.UTC, false)
|
return basic.JDE2DateByZone(jde, time.UTC, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NextXiaXianYue(date time.Time) time.Time {
|
||||||
|
return nextMoonPhase(date, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LastXiaXianYue(date time.Time) time.Time {
|
||||||
|
return lastMoonPhase(date, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClosestXiaXianYue(date time.Time) time.Time {
|
||||||
|
return closestMoonPhase(date, 3)
|
||||||
|
}
|
||||||
|
|
||||||
// EarthDistance 日地距离
|
// EarthDistance 日地距离
|
||||||
// 返回date对应UTC世界时日地距离
|
// 返回date对应UTC世界时日地距离
|
||||||
func EarthDistance(date time.Time) float64 {
|
func EarthDistance(date time.Time) float64 {
|
||||||
|
@ -6,6 +6,49 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Rise(t *testing.T) {
|
func Test_MoonPhaseDate(t *testing.T) {
|
||||||
fmt.Println(RiseTime(time.Now(), 120, 40, 10, true))
|
//指定北京时间2022年1月20日
|
||||||
|
tz := time.FixedZone("CST", 8*3600)
|
||||||
|
date := time.Date(2022, 01, 20, 00, 00, 00, 00, tz)
|
||||||
|
//指定日期后的下一个朔月
|
||||||
|
moonPhase01 := NextShuoYue(date)
|
||||||
|
fmt.Println("下一朔月", moonPhase01)
|
||||||
|
if moonPhase01.Unix() != 1643694349 {
|
||||||
|
t.Fatal(moonPhase01)
|
||||||
|
}
|
||||||
|
//指定日期后的上一个朔月
|
||||||
|
moonPhase01 = LastShuoYue(date)
|
||||||
|
fmt.Println("上一朔月", moonPhase01)
|
||||||
|
if moonPhase01.Unix() != 1641148399 {
|
||||||
|
t.Fatal(moonPhase01)
|
||||||
|
}
|
||||||
|
//离指定日期最近的朔月
|
||||||
|
moonPhase01 = ClosestShuoYue(date)
|
||||||
|
fmt.Println("最近朔月", moonPhase01)
|
||||||
|
if moonPhase01.Unix() != 1643694349 {
|
||||||
|
t.Fatal(moonPhase01)
|
||||||
|
}
|
||||||
|
//离指定日期最近的望月时间
|
||||||
|
moonPhase01 = ClosestWangYue(date)
|
||||||
|
fmt.Println("最近望月", moonPhase01)
|
||||||
|
if moonPhase01.Unix() != 1642463294 {
|
||||||
|
t.Fatal(moonPhase01)
|
||||||
|
}
|
||||||
|
//离指定日期最近的上弦月时间
|
||||||
|
moonPhase01 = ClosestShangXianYue(date)
|
||||||
|
fmt.Println("最近上弦月", moonPhase01)
|
||||||
|
if moonPhase01.Unix() != 1641751864 {
|
||||||
|
t.Fatal(moonPhase01)
|
||||||
|
}
|
||||||
|
//离指定日期最近的下弦月时间
|
||||||
|
moonPhase01 = ClosestXiaXianYue(date)
|
||||||
|
fmt.Println("最近下弦月", moonPhase01)
|
||||||
|
if moonPhase01.Unix() != 1643118043 {
|
||||||
|
t.Fatal(moonPhase01)
|
||||||
|
}
|
||||||
|
//-------------------
|
||||||
|
for i := 0; i < 26; i++ {
|
||||||
|
moonPhase01 = LastShuoYue(moonPhase01)
|
||||||
|
fmt.Println("上一朔月", moonPhase01)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user