diff --git a/astro.go b/astro.go index 5bfc3f6..f5bcf2d 100644 --- a/astro.go +++ b/astro.go @@ -1,196 +1,2 @@ +// Package astro package astro - -import ( - "errors" - "time" - - "b612.me/astro/basic" -) - -/* -获取当前时刻(本地时间)对应的儒略日时间 -*/ -func NowJDE() float64 { - return basic.GetNowJDE() -} - -/* -日期转儒略日 -*/ -func Date2JDE(date time.Time) float64 { - day := float64(date.Day()) + float64(date.Hour())/24.0 + float64(date.Minute())/24.0/60.0 + float64(date.Second())/24.0/3600.0 + float64(date.Nanosecond())/1000000000.0/3600.0/24.0 - return basic.JDECalc(date.Year(), int(date.Month()), day) -} - -/* -儒略日转日期 -*/ -func JDE2Date(jde float64) time.Time { - return basic.JDE2Date(jde) -} - -/* -公历转农历 -返回:月,日,是否闰月,文字描述 -*/ -func Lunar(year, month, day int) (int, int, bool, string) { - return basic.GetLunar(year, month, day) -} - -/* -农历转公历 -*/ -func Solar(year, month, day int, leap bool) time.Time { - jde := basic.GetSolar(year, month, day, leap) - return JDE2Date(jde) -} - -/* - 太阳升起时间 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - aero,true时进行大气修正 -*/ -func SunRiseTime(jde, lon, lat, timezone float64, aero bool) (time.Time, error) { - var err error = nil - tz := 0.00 - if aero { - tz = 1 - } - tm := basic.GetSunRiseTime(jde, lon, lat, timezone, tz) - if tm == -2 { - err = errors.New("极夜") - } - if tm == -1 { - err = errors.New("极昼") - } - return JDE2Date(tm), err -} - -/* - 太阳落下时间 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - aero,true时进行大气修正 -*/ -func SunDownTime(jde, lon, lat, timezone float64, aero bool) (time.Time, error) { - var err error = nil - tz := 0.00 - if aero { - tz = 1 - } - tm := basic.GetSunDownTime(jde, lon, lat, timezone, tz) - if tm == -2 { - err = errors.New("极夜") - } - if tm == -1 { - err = errors.New("极昼") - } - return JDE2Date(tm), err -} - -/* - 晨朦影 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - angle,朦影角度:可选-6 -12 -18 -*/ -func MorningTwilightTime(jde, lon, lat, timezone, angle float64) (time.Time, error) { - var err error = nil - tm := basic.GetAsaTime(jde, lon, lat, timezone, angle) - if tm == -2 { - err = errors.New("不存在") - } - if tm == -1 { - err = errors.New("不存在") - } - return JDE2Date(tm), err -} - -/* - 昏朦影 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - angle,朦影角度:可选-6 -12 -18 -*/ -func EveningTwilightTime(jde, lon, lat, timezone, angle float64) (time.Time, error) { - var err error = nil - tm := basic.GetBanTime(jde, lon, lat, timezone, angle) - if tm == -2 { - err = errors.New("不存在") - } - if tm == -1 { - err = errors.New("不存在") - } - return JDE2Date(tm), err -} - -/* - 月亮升起时间 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - aero,true时进行大气修正 -*/ -func MoonRiseTime(jde, lon, lat, timezone float64, aero bool) (time.Time, error) { - var err error = nil - tz := 0.00 - if aero { - tz = 1 - } - tm := basic.GetMoonRiseTime(jde, lon, lat, timezone, tz) - if tm == -3 { - err = errors.New("非今日") - } - if tm == -2 { - err = errors.New("极夜") - } - if tm == -1 { - err = errors.New("极昼") - } - return JDE2Date(tm), err -} - -/* - 月亮落下时间 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - aero,true时进行大气修正 -*/ -func MoonDownTime(jde, lon, lat, timezone float64, aero bool) (time.Time, error) { - var err error = nil - tz := 0.00 - if aero { - tz = 1 - } - tm := basic.GetMoonDownTime(jde, lon, lat, timezone, tz) - if tm == -3 { - err = errors.New("非今日") - } - if tm == -2 { - err = errors.New("极夜") - } - if tm == -1 { - err = errors.New("极昼") - } - return JDE2Date(tm), err -} - -/* -月相 -jde,世界时UTC JDE -*/ -func Phase(jde float64) float64 { - return basic.MoonLight(basic.TD2UT(jde, true)) -} diff --git a/basic/calendar.go b/basic/calendar.go index c0f0c4e..ae8e232 100644 --- a/basic/calendar.go +++ b/basic/calendar.go @@ -70,12 +70,12 @@ func dt_cal(y float64) float64 { //传入年, 返回世界时UT与原子时( if y >= y0 { jsd := float64(31) // sjd是y1年之后的加速度估计 // 瑞士星历表jsd=31, NASA网站jsd=32, skmap的jsd=29 - if y > y0+100 { + if y > y0+100.00 { return dt_ext(y, jsd) } v := dt_ext(y, jsd) //二次曲线外推 dv := dt_ext(y0, jsd) - t0 // ye年的二次外推与te的差 - return (v - dv*(y0+100-y)/100) + return (v - dv*(y0+100.00-y)/100.00) } d := dt_at var i int @@ -85,7 +85,7 @@ func dt_cal(y float64) float64 { //传入年, 返回世界时UT与原子时( // 判断年所在的区间 } } - t1 := (y - d[i]) / (d[i+5] - d[i]) * 10 //////// 三次插值, 保证精确性 + t1 := (y - d[i]) / (d[i+5] - d[i]) * 10.00 //////// 三次插值, 保证精确性 t2 := t1 * t1 t3 := t2 * t1 res := d[i+1] + d[i+2]*t1 + d[i+3]*t2 + d[i+4]*t3 @@ -94,7 +94,8 @@ func dt_cal(y float64) float64 { //传入年, 返回世界时UT与原子时( func DeltaT(Date float64, IsJDE bool) (Result float64) { //传入年或儒略日,传出为秒 var Year float64 if IsJDE { - Year = (Date-2451545.0)/365.25 + 0.1 + 2000 + dates := JDE2Date(Date) + Year = float64(dates.Year()) + float64(dates.YearDay())/365.0 } else { Year = Date } @@ -103,6 +104,7 @@ func DeltaT(Date float64, IsJDE bool) (Result float64) { //传入年或儒略日 return } if Year < 2100 && Year >= 2010 { + //fmt.Println(Year) Result = dt_cal(Year) //-3.2-(Year-2017)*0.029915; return } @@ -167,6 +169,41 @@ func JDE2Date(JD float64) time.Time { return dates } +func JDE2DateByZone(JD float64, tz *time.Location) time.Time { + JD = JD + 0.5 + Z := float64(int(JD)) + F := JD - Z + var A, B, Years, Months, Days float64 + if Z < 2299161.0 { + A = Z + } else { + alpha := math.Floor((Z - 1867216.25) / 36524.25) + A = Z + 1 + alpha - math.Floor(alpha/4) + } + B = A + 1524 + C := math.Floor((B - 122.1) / 365.25) + D := math.Floor(365.25 * C) + E := math.Floor((B - D) / 30.6001) + Days = B - D - math.Floor(30.6001*E) + F + if E < 14 { + Months = E - 1 + } + if E == 14 || E == 15 { + Months = E - 13 + } + if Months > 2 { + Years = C - 4716 + } + if Months == 1 || Months == 2 { + Years = C - 4715 + } + tms := (Days - math.Floor(Days)) * 24 * 3600 + Days = math.Floor(Days) + dates := time.Date(int(Years), time.Month(int(Months)), int(Days), 0, 0, 0, 0, tz) + dates = time.Unix(dates.Unix()+int64(tms), int64((tms-math.Floor(tms))*1000000000)) + return dates +} + func GetLunar(year, month, day int) (lmonth, lday int, leap bool, result string) { jde := JDECalc(year, month, float64(day)) //计算当前JDE时间 if month == 11 || month == 12 { //判断当前日期属于前一年周期还是后一年周期 @@ -321,3 +358,9 @@ func GetSolar(year, month, day int, leap bool) float64 { jde := moon[min-1+month] + float64(day) - 1 return jde } + +// Date2JDE 日期转儒略日 +func Date2JDE(date time.Time) float64 { + day := float64(date.Day()) + float64(date.Hour())/24.0 + float64(date.Minute())/24.0/60.0 + float64(date.Second())/24.0/3600.0 + float64(date.Nanosecond())/1000000000.0/3600.0/24.0 + return JDECalc(date.Year(), int(date.Month()), day) +} diff --git a/basic/coordinate_test.go b/basic/coordinate_test.go index c3217e9..6b51083 100644 --- a/basic/coordinate_test.go +++ b/basic/coordinate_test.go @@ -6,5 +6,5 @@ import ( ) func Test_LoBo(t *testing.T) { - fmt.Sprintf("%.14f", LoToRa(22, 33, 2451545.0)) + fmt.Printf("%.9f", dt_cal(2020.5)) } diff --git a/basic/moon.go b/basic/moon.go index 39b78a7..8e54283 100644 --- a/basic/moon.go +++ b/basic/moon.go @@ -1420,9 +1420,9 @@ func GetMoonRiseTime(JD, Lon, Lat, TZ, ZS float64) float64 { } if moonheight < 0 && moonang > 180 { tms = (180 - moonang) / 15 - JD1 += (tms/24 + (tms/24*12.0)/15.0/24.0) + JD1 = JD1 - (tms/24 + (tms/24*12.0)/15.0/24.0) } else if moonheight < 0 && moonang < 180 { - tms = (-180 + moonang) / 15 + tms = (180 - moonang) / 15 JD1 += (tms/24 + (tms/24*12.0)/15.0/24.0) } now := MoonTimeAngle(JD1, Lon, Lat, TZ) diff --git a/basic/sun.go b/basic/sun.go index d4a696d..1c9ec3a 100644 --- a/basic/sun.go +++ b/basic/sun.go @@ -903,21 +903,34 @@ func HSunTrueLo(JD float64) float64 { return L } +func HSunTrueBo(JD float64) float64 { + L := planet.WherePlanet(0, 1, JD) + return L +} + func HSunSeeLo(JD float64) float64 { - t := (JD - 2451545) / 365250.0 L := HSunTrueLo(JD) - R := planet.WherePlanet(-1, 2, JD) - t2 := t * t - t3 := t2 * t //千年数的各次方 - R += (-0.0020 + 0.0044*t + 0.0213*t2 - 0.0250*t3) - L = L + HJZD(JD) - 20.4898/R/3600 + /* + t := (JD - 2451545) / 365250.0 + R := planet.WherePlanet(-1, 2, JD) + t2 := t * t + t3 := t2 * t //千年数的各次方 + R += (-0.0020 + 0.0044*t + 0.0213*t2 - 0.0250*t3) + L = L + HJZD(JD) - 20.4898/R/3600.00 + */ + L = L + HJZD(JD) + SunLoGXC(JD) return L } +func SunLoGXC(JD float64) float64 { + R := planet.WherePlanet(0, 2, JD) + return -20.49552 / R / 3600 +} + func EarthAway(JD float64) float64 { //t=(JD - 2451545) / 365250; //R=Earth_R5(t)+Earth_R4(t)+Earth_R3(t)+Earth_R2(t)+Earth_R1(t)+Earth_R0(t); - return planet.WherePlanet(0, 2, 2555555) + return planet.WherePlanet(0, 2, JD) } func HSunSeeRaDec(JD float64) (float64, float64) { diff --git a/basic/sun_test.go b/basic/sun_test.go index 305a079..a5c450a 100644 --- a/basic/sun_test.go +++ b/basic/sun_test.go @@ -7,10 +7,14 @@ import ( ) func Test_Jq(t *testing.T) { - //fmt.Println(GetOneYearJQ(2019)) - fmt.Println(JDE2Date(GetWHTime(2019, 10))) - fmt.Println(JDE2Date(GetJQTime(2019, 15))) - fmt.Println(JDE2Date(GetJQTime(2019, 0))) + data := GetOneYearJQ(2019) + for i := 1; i < 25; i++ { + fmt.Println(JDE2Date(data[i])) + } + //fmt.Println(JDE2Date(GetWHTime(2019, 10))) + //fmt.Println(JDE2Date(GetJQTime(2020, 0))) + //date := TD2UT(GetJQTime(2020, 0), true) + //fmt.Println(HSunSeeLo(date)) } func Test_SunLo(t *testing.T) { diff --git a/calendar/astro.go b/calendar/astro.go new file mode 100644 index 0000000..6aa797e --- /dev/null +++ b/calendar/astro.go @@ -0,0 +1,25 @@ +package calendar + +import ( + "time" + + "b612.me/astro/basic" +) + +// NowJDE 获取当前时刻(本地时间)对应的儒略日时间 +func NowJDE() float64 { + return basic.GetNowJDE() +} + +// Date2JDE 日期转儒略日 +func Date2JDE(date time.Time) float64 { + day := float64(date.Day()) + float64(date.Hour())/24.0 + float64(date.Minute())/24.0/60.0 + float64(date.Second())/24.0/3600.0 + float64(date.Nanosecond())/1000000000.0/3600.0/24.0 + return basic.JDECalc(date.Year(), int(date.Month()), day) +} + +// JDE2Date 儒略日转日期 +func JDE2Date(jde float64) time.Time { + return basic.JDE2Date(jde) +} + + diff --git a/calendar/chinese.go b/calendar/chinese.go new file mode 100644 index 0000000..597e4e0 --- /dev/null +++ b/calendar/chinese.go @@ -0,0 +1,79 @@ +package calendar + +import ( + "time" + + "b612.me/astro/basic" +) + +const ( + JQ_春分 = 15 * iota + JQ_清明 + JQ_谷雨 + JQ_立夏 + JQ_小满 + JQ_芒种 + JQ_夏至 + JQ_小暑 + JQ_大暑 + JQ_立秋 + JQ_处暑 + JQ_白露 + JQ_秋分 + JQ_寒露 + JQ_霜降 + JQ_立冬 + JQ_小雪 + JQ_大雪 + JQ_冬至 + JQ_小寒 + JQ_大寒 + JQ_立春 + JQ_雨水 + JQ_惊蛰 +) + +// Lunar 公历转农历 +// 传入 公历年月日 +// 返回 农历月,日,是否闰月以及文字描述 +func Lunar(year, month, day int) (int, int, bool, string) { + return basic.GetLunar(year, month, day) +} + +// ChineseLunar 公历转农历 +// 传入 公历年月日 +// 返回 农历月,日,是否闰月以及文字描述 +// 忽略时区,日期一律按北京时间计算 +func ChineseLunar(date time.Time) (int, int, bool, string) { + return basic.GetLunar(date.Year(), int(date.Month()), date.Day()) +} + +// Solar 农历转公历 +// 传入 农历年份,月,日,是否闰月 +// 传出 公历时间 +// 农历年份用公历年份代替,但是岁首需要使用农历岁首 +// 例:计算己亥猪年腊月三十日对应的公历(即2020年1月24日) +// 由于农历还未到鼠年,故应当传入Solar(2019,12,30,false) +func Solar(year, month, day int, leap bool) time.Time { + jde := basic.GetSolar(year, month, day, leap) + return JDE2Date(jde) +} + +// GanZhi 返回传入年份对应的干支 +func GanZhi(year int) string { + return basic.GetGZ(year) +} + +// JieQi 返回传入年份、节气对应的北京时间节气时间 +func JieQi(year, term int) time.Time { + calcJde := basic.GetJQTime(year, term) + 8.00/24.00 + zone := time.FixedZone("CST", 8*3600) + return basic.JDE2DateByZone(calcJde, zone) +} + +// WuHou 返回传入年份、物候对应的北京时间物候时间 +func WuHou(year, term int) time.Time { + calcJde := basic.GetWHTime(year, term) + 8.00/24.00 + zone := time.FixedZone("CST", 8*3600) + return basic.JDE2DateByZone(calcJde, zone) +} diff --git a/earth/earth.go b/earth/earth.go index 6ee6f0c..84a6999 100644 --- a/earth/earth.go +++ b/earth/earth.go @@ -1,14 +1,14 @@ package earth import ( + "time" + "b612.me/astro/basic" ) -/* -地球偏心率 -jde, utc世界时 -*/ - -func EarthEccentricity(jde float64) float64 { +// EarthEccentricity 地球偏心率 +// 返回date对应UTC时间的地球偏心率 +func EarthEccentricity(date time.Time) float64 { + jde := basic.Date2JDE(date.UTC()) return basic.Earthe(basic.TD2UT(jde, true)) } diff --git a/moon/moon.go b/moon/moon.go index b879760..f014e39 100644 --- a/moon/moon.go +++ b/moon/moon.go @@ -2,208 +2,190 @@ package moon import ( "errors" + "time" "b612.me/astro/basic" ) -/* - 月亮真黄经 - jde,世界时UTC -*/ -func TrueLo(jde float64) float64 { +var ( + ERR_MOON_NEVER_RISE = errors.New("ERROR:极夜,月亮在今日永远在地平线下!") + ERR_MOON_NEVER_DOWN = errors.New("ERROR:极昼,月亮在今日永远在地平线上!") + ERR_NOT_TODAY = errors.New("ERROR:月亮已在(昨日/明日)(升起/降下)") +) + +// TrueLo 月亮真黄经 +func TrueLo(date time.Time) float64 { + jde := basic.Date2JDE(date.UTC()) return basic.HMoonTrueLo(basic.TD2UT(jde, true)) } -/* - 月亮视黄经 - jde,世界时UTC -*/ -func SeeLo(jde float64) float64 { +// TrueBo 月亮真黄纬 +func TrueBo(date time.Time) float64 { + jde := basic.Date2JDE(date.UTC()) + return basic.HMoonTrueBo(basic.TD2UT(jde, true)) +} + +// SeeLo 月亮视黄经(地心) +// 传入UTC对应的儒略日时间 +func SeeLo(date time.Time) float64 { + jde := basic.Date2JDE(date.UTC()) return basic.HMoonSeeLo(basic.TD2UT(jde, true)) } -/* - 月亮视赤经 - jde,世界时UTC - lon, 经度 - lat, 纬度 - timezone, 时区 - 返回站心坐标 -*/ -func SeeRa(jde, lon, lat, timezone float64) float64 { +// SeeRa 月亮视赤经(站心) +// jde,世界时UTC +// lon, 经度 +// lat, 纬度 +// timezone, 时区 +// 返回站心坐标 +func SeeRa(date time.Time, lon, lat, timezone float64) float64 { + jde := basic.Date2JDE(date) return basic.HMoonSeeRa(basic.TD2UT(jde, true), lon, lat, timezone) } -/* - 月亮视赤纬 - jde,世界时UTC - lon, 经度 - lat, 纬度 - timezone, 时区 - 返回站心坐标 -*/ -func SeeDec(jde, lon, lat, timezone float64) float64 { +// SeeDec 月亮视赤纬(站心) +// jde,世界时UTC +// lon, 经度 +// lat, 纬度 +// timezone, 时区 +// 返回站心坐标 +func SeeDec(date time.Time, lon, lat, timezone float64) float64 { + jde := basic.Date2JDE(date) return basic.HMoonSeeDec(basic.TD2UT(jde, true), lon, lat, timezone) } -/* - 月亮视赤经赤纬 - jde,世界时UTC - lon, 经度 - lat, 纬度 - timezone, 时区 - 返回站心坐标 -*/ -func SeeRaDec(jde, lon, lat, timezone float64) (float64, float64) { +// SeeRaDec 月亮视赤纬(站心) +// jde,世界时UTC +// lon, 经度 +// lat, 纬度 +// timezone, 时区 +// 返回站心坐标 +func SeeRaDec(date time.Time, lon, lat, timezone float64) (float64, float64) { + jde := basic.Date2JDE(date) return basic.HMoonSeeRaDec(basic.TD2UT(jde, true), lon, lat, timezone) } -/* - 月亮真赤经 - jde,世界时UTC -*/ -func TrueRa(jde float64) float64 { - return basic.HMoonTrueRa(basic.TD2UT(jde, true)) -} - -/* - 月亮真赤纬 - jde,世界时UTC -*/ -func TrueDec(jde float64) float64 { - return basic.HMoonTrueDec(basic.TD2UT(jde, true)) -} - -/* - 月亮时角 - jde,世界时当地时间 - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 -*/ -func HourAngle(jde, lon, lat, timezone float64) float64 { +// HourAngle 月亮时角 +// date, 世界时(忽略此处时区) +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +func HourAngle(date time.Time, lon, lat, timezone float64) float64 { + jde := basic.Date2JDE(date) return basic.MoonTimeAngle(jde, lon, lat, timezone) } -/* - 月亮方位角 - jde,世界时当地时间 - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 -*/ -func Azimuth(jde, lon, lat, timezone float64) float64 { +// Azimuth 月亮方位角 +// date, 世界时(忽略此处时区) +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +func Azimuth(date time.Time, lon, lat, timezone float64) float64 { + jde := basic.Date2JDE(date) return basic.HMoonAngle(jde, lon, lat, timezone) } -/* - 月亮高度角 - jde,世界时当地时间 - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 -*/ -func Zenith(jde, lon, lat, timezone float64) float64 { +// Zenith 月亮高度角 +// date, 世界时(忽略此处时区) +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +func Zenith(date time.Time, lon, lat, timezone float64) float64 { + jde := basic.Date2JDE(date) return basic.HMoonHeight(jde, lon, lat, timezone) } -/* - 月亮中天时间 - jde,世界时当地0时 - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 -*/ -func CulminationTime(jde, lon, lat, timezone float64) float64 { +// CulminationTime 月亮中天时间 +// date, 世界时(忽略此处时区) +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +func CulminationTime(date time.Time, lon, lat, timezone float64) float64 { + jde := basic.Date2JDE(date) return basic.GetMoonTZTime(jde, lon, lat, timezone) } -/* - 月亮升起时间 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - aero,true时进行大气修正 -*/ -func RiseTime(jde, lon, lat, timezone float64, aero bool) (float64, error) { - var err error = nil - tz := 0.00 +// RiseTime 月亮升起时间 +// date, 世界时(忽略此处时区) +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +func RiseTime(date time.Time, lon, lat, timezone float64, aero bool) (time.Time, error) { + var err error + jde := basic.Date2JDE(date) + aeroFloat := 0.00 if aero { - tz = 1 + aeroFloat = 1 } - tm := basic.GetMoonRiseTime(jde, lon, lat, timezone, tz) - if tm == -3 { - err = errors.New("非今日") + riseJde := basic.GetMoonRiseTime(jde, lon, lat, timezone, aeroFloat) + if riseJde == -3 { + err = ERR_NOT_TODAY } - if tm == -2 { - err = errors.New("极夜") + if riseJde == -2 { + err = ERR_MOON_NEVER_RISE } - if tm == -1 { - err = errors.New("极昼") + if riseJde == -1 { + err = ERR_MOON_NEVER_DOWN } - return tm, err -} - -/* - 月亮落下时间 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - aero,true时进行大气修正 -*/ -func DownTime(jde, lon, lat, timezone float64, aero bool) (float64, error) { - var err error = nil - tz := 0.00 + return basic.JDE2Date(riseJde), err +} + +// DownTime 月亮降下时间 +// date, 世界时(忽略此处时区) +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +func DownTime(date time.Time, lon, lat, timezone float64, aero bool) (time.Time, error) { + var err error + jde := basic.Date2JDE(date) + aeroFloat := 0.00 if aero { - tz = 1 + aeroFloat = 1 } - tm := basic.GetMoonDownTime(jde, lon, lat, timezone, tz) - if tm == -3 { - err = errors.New("非今日") + downJde := basic.GetMoonDownTime(jde, lon, lat, timezone, aeroFloat) + if downJde == -3 { + err = ERR_NOT_TODAY } - if tm == -2 { - err = errors.New("极夜") + if downJde == -2 { + err = ERR_MOON_NEVER_RISE } - if tm == -1 { - err = errors.New("极昼") + if downJde == -1 { + err = ERR_MOON_NEVER_DOWN } - return tm, err + return basic.JDE2Date(downJde), err } -/* -月相 -jde,世界时UTC JDE -*/ -func Phase(jde float64) float64 { +// Phase 月相 +// 返回Date对应UTC世界时的月相大小 +func Phase(date time.Time) float64 { + jde := basic.Date2JDE(date.UTC()) return basic.MoonLight(basic.TD2UT(jde, true)) } -/* -朔月 -*/ +// ShuoYue 朔月 func ShuoYue(year float64) float64 { return basic.CalcMoonSH(year, 0) } -/* -望月 -*/ +// WangYue 望月 func WangYue(year float64) float64 { return basic.CalcMoonSH(year, 1) } -/* -上弦月 -*/ +// ShangXianYue 上弦月 func ShangXianYue(year float64) float64 { return basic.CalcMoonXH(year, 0) } -/* -下弦月 -*/ +// XiaXianYue 下弦月 func XiaXianYue(year float64) float64 { return basic.CalcMoonXH(year, 1) } + +// EarthDistance 日地距离 +// 返回date对应UTC世界时日地距离 +func EarthDistance(date time.Time) float64 { + jde := basic.Date2JDE(date) + jde = basic.TD2UT(jde, true) + return basic.MoonAway(jde) +} diff --git a/star/star.go b/star/star.go new file mode 100644 index 0000000..7b47878 --- /dev/null +++ b/star/star.go @@ -0,0 +1,15 @@ +package star + +import ( + "time" + + "b612.me/astro/basic" +) + +// Constellation +// 计算date对应UTC世界时给定Date坐标赤经、赤纬所在的星座 + +func Constellation(ra, dec float64, date time.Time) string { + jde := basic.Date2JDE(date.UTC()) + return basic.WhichCst(ra, dec, jde) +} diff --git a/sun/sun.go b/sun/sun.go index f10f81f..dfb7e7c 100644 --- a/sun/sun.go +++ b/sun/sun.go @@ -2,243 +2,251 @@ package sun import ( "errors" + "math" + "time" "b612.me/astro/basic" ) +var ( + ERR_SUN_NEVER_RISE = errors.New("ERROR:极夜,太阳在今日永远在地平线下!") + ERR_SUN_NEVER_DOWN = errors.New("ERROR:极昼,太阳在今日永远在地平线上!") + ERR_TWILIGHT_NOT_EXISTS = errors.New("ERROR:今日晨昏朦影不存在!") +) + /* - 黄赤交角 - jde,世界时UTC - nutation,为true时计算交角章动 +太阳 +视星等 −26.74 +绝对星等 4.839 +光谱类型 G2V +金属量 Z = 0.0122 +角直径 31.6′ – 32.7′ */ -func EclipticObliquity(jde float64, nutation bool) float64 { + +// RiseTime 太阳升起时间 +// date,取日期,时区忽略 +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +// aero,true时进行大气修正 +func RiseTime(date time.Time, lon, lat, timezone float64, aero bool) (time.Time, error) { + var err error + var aeroFloat float64 + if aero { + aeroFloat = 1 + } + jde := basic.Date2JDE(date) + riseJde := basic.GetSunRiseTime(jde, lon, lat, timezone, aeroFloat) + if riseJde == -2 { + err = ERR_SUN_NEVER_RISE + } + if riseJde == -1 { + err = ERR_SUN_NEVER_DOWN + } + return basic.JDE2Date(riseJde), err +} + +// SunDownTime 太阳落下时间 +// date,取日期,时区忽略 +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +// aero,true时进行大气修正 +func DownTime(date time.Time, lon, lat, timezone float64, aero bool) (time.Time, error) { + var err error + var aeroFloat float64 + if aero { + aeroFloat = 1 + } + jde := basic.Date2JDE(date) + downJde := basic.GetSunDownTime(jde, lon, lat, timezone, aeroFloat) + if downJde == -2 { + err = ERR_SUN_NEVER_RISE + } + if downJde == -1 { + err = ERR_SUN_NEVER_DOWN + } + return basic.JDE2Date(downJde), err +} + +// MorningTwilight 晨朦影 +// date,取日期,时区忽略 +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +// angle,朦影角度:可选-6 -12 -18(民用、航海、天文) +func MorningTwilight(date time.Time, lon, lat, timezone, angle float64) (time.Time, error) { + var err error + jde := basic.Date2JDE(date) + calcJde := basic.GetAsaTime(jde, lon, lat, timezone, angle) + if calcJde == -2 { + err = ERR_TWILIGHT_NOT_EXISTS + } + if calcJde == -1 { + err = ERR_TWILIGHT_NOT_EXISTS + } + return basic.JDE2Date(calcJde), err +} + +// EveningTwilight 昏朦影 +// date,取日期,时区忽略 +// lon,经度,东正西负 +// lat,纬度,北正南负 +// timezone,时区,东正西负 +// angle,朦影角度:可选-6 -12 -18(民用、航海、天文) +func EveningTwilight(date time.Time, lon, lat, timezone, angle float64) (time.Time, error) { + var err error + jde := basic.Date2JDE(date) + //不需要进行力学时转换,会在GetBanTime中转换 + calcJde := basic.GetBanTime(jde, lon, lat, timezone, angle) + if calcJde == -2 { + err = ERR_TWILIGHT_NOT_EXISTS + } + if calcJde == -1 { + err = ERR_TWILIGHT_NOT_EXISTS + } + return basic.JDE2Date(calcJde), err +} + +// EclipticObliquity 黄赤交角 +// 返回date对应UTC世界时的黄赤交角,nutation为true时,计算交角章动 +func EclipticObliquity(date time.Time, nutation bool) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) + //进行力学时转换 jde = basic.TD2UT(jde, true) + //黄赤交角计算 return basic.EclipticObliquity(jde, nutation) } -/* - 黄经章动 - jde,世界时UTC -*/ -func EclipticNutation(jde float64) float64 { +// EclipticNutation 黄经章动 +// 返回date对应UTC世界时的黄经章动 +func EclipticNutation(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) + //进行力学时转换与章动计算 return basic.HJZD(basic.TD2UT(jde, true)) } -/* - 交角章动 - jde,世界时UTC -*/ -func AxialtiltNutation(jde float64) float64 { +// AxialtiltNutation 交角章动 +// 返回date对应UTC世界时的交角章动 +func AxialtiltNutation(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) + //进行力学时转换与章动计算 return basic.JJZD(basic.TD2UT(jde, true)) } -/* - 太阳几何黄经 - jde,世界时UTC -*/ -func GeometricLo(jde float64) float64 { +// GeometricLo 太阳几何黄经 +// 返回date对应UTC世界时的太阳几何黄经 +func GeometricLo(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) return basic.SunLo(basic.TD2UT(jde, true)) } -/* - 太阳真黄经 - jde,世界时UTC -*/ -func TrueLo(jde float64) float64 { +// TrueLo 太阳真黄经 +// 返回date对应UTC世界时的太阳真黄经 +func TrueLo(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) return basic.HSunTrueLo(basic.TD2UT(jde, true)) } -/* - 太阳视黄经 - jde,世界时UTC -*/ -func SeeLo(jde float64) float64 { +// TrueBo 太阳真黄纬 +// 返回date对应UTC世界时的太阳真黄纬 +func TrueBo(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) + return basic.HSunTrueLo(basic.TD2UT(jde, true)) +} + +// SeeLo 太阳视黄经 +// 返回date对应UTC世界时的太阳视黄经 +func SeeLo(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) return basic.HSunSeeLo(basic.TD2UT(jde, true)) } -/* - 太阳视赤经 - jde,世界时UTC -*/ -func SeeRa(jde float64) float64 { +// SeeRa 太阳地心视赤经 +// 返回date对应UTC世界时的太阳视赤经(使用黄道坐标转换,且默认忽略黄纬) +func SeeRa(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) return basic.HSunSeeRa(basic.TD2UT(jde, true)) } -/* - 太阳视赤纬 - jde,世界时UTC -*/ -func SeeDec(jde float64) float64 { +// SeeDec 太阳地心视赤纬 +// 返回date对应UTC世界时的太阳视赤纬(使用黄道坐标转换,且默认忽略黄纬) +func SeeDec(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) return basic.HSunSeeDec(basic.TD2UT(jde, true)) } -/* - 太阳视赤经赤纬 - jde,世界时UTC -*/ -func SeeRaDec(jde float64) (float64, float64) { +// SeeRaDec 太阳地心视赤经和赤纬 +// 返回date对应UTC世界时的太阳视赤纬(使用黄道坐标转换,且默认忽略黄纬) +func SeeRaDec(date time.Time) (float64, float64) { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) return basic.HSunSeeRaDec(basic.TD2UT(jde, true)) } -/* - 太阳真赤经 - jde,世界时UTC -*/ -func TrueRa(jde float64) float64 { - return basic.HSunTrueRa(basic.TD2UT(jde, true)) -} - -/* - 太阳真赤纬 - jde,世界时UTC -*/ -func TrueDec(jde float64) float64 { - return basic.HSunTrueDec(basic.TD2UT(jde, true)) -} - -/* - 太阳中间方程 - jde,世界时UTC -*/ -func MidFunc(jde float64) float64 { +// MidFunc 太阳中间方程 +func MidFunc(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) return basic.SunMidFun(basic.TD2UT(jde, true)) } -/* - 均时差 - jde,世界时UTC -*/ -func EquationTime(jde float64) float64 { +// EquationTime 均时差 +// 返回date对应UTC世界时的均时差 +func EquationTime(date time.Time) float64 { + //转换为UTC时间 + jde := basic.Date2JDE(date.UTC()) return basic.SunTime(basic.TD2UT(jde, true)) } -/* - 太阳时角 - jde,世界时当地时间 - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 -*/ -func HourAngle(jde, lon, lat, timezone float64) float64 { +// HourAngle 太阳时角 +// 返回给定经纬度、对应timezone时区date时刻的太阳时角(注意,date本身的时区将默认舍去) +func HourAngle(date time.Time, lon, lat, timezone float64) float64 { + jde := basic.Date2JDE(date) return basic.SunTimeAngle(jde, lon, lat, timezone) } -/* - 太阳方位角 - jde,世界时当地时间 - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 -*/ -func Azimuth(jde, lon, lat, timezone float64) float64 { +// Azimuth 太阳方位角 +// 返回给定经纬度、对应timezone时区date时刻的太阳方位角(正北为0,向东增加) +//(注意,date本身的时区将默认舍去) +func Azimuth(date time.Time, lon, lat, timezone float64) float64 { + jde := basic.Date2JDE(date) return basic.SunAngle(jde, lon, lat, timezone) } -/* - 太阳高度角 - jde,世界时当地时间 - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 -*/ -func Zenith(jde, lon, lat, timezone float64) float64 { +// Zenith 太阳高度角 +// 返回给定经纬度、对应timezone时区date时刻的太阳高度角 +//(注意,date本身的时区将默认舍去) +func Zenith(date time.Time, lon, lat, timezone float64) float64 { + jde := basic.Date2JDE(date) return basic.SunHeight(jde, lon, lat, timezone) } -/* - 太阳中天时间 - jde,世界时当地0时 - lon,经度,东正西负 - timezone,时区,东正西负 -*/ -func CulminationTime(jde, lon, timezone float64) float64 { - return basic.GetSunTZTime(jde, lon, timezone) -} - -/* - 太阳升起时间 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - aero,true时进行大气修正 -*/ -func RiseTime(jde, lon, lat, timezone float64, aero bool) (float64, error) { - var err error = nil - tz := 0.00 - if aero { - tz = 1 - } - tm := basic.GetSunRiseTime(jde, lon, lat, timezone, tz) - if tm == -2 { - err = errors.New("极夜") +// CulminationTime 太阳中天时间 +// 返回给定经纬度、对应timezone时区date时刻的太阳中天日期 +//(注意,date本身的时区将默认舍去,返回的时间时区应当为传入的timezone) +func CulminationTime(date time.Time, lon, timezone float64) time.Time { + jde := basic.Date2JDE(date) + if jde-math.Floor(jde) > 0.5 { + jde++ } - if tm == -1 { - err = errors.New("极昼") - } - return tm, err -} - -/* - 太阳落下时间 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - aero,true时进行大气修正 -*/ -func DownTime(jde, lon, lat, timezone float64, aero bool) (float64, error) { - var err error = nil - tz := 0.00 - if aero { - tz = 1 - } - tm := basic.GetSunDownTime(jde, lon, lat, timezone, tz) - if tm == -2 { - err = errors.New("极夜") - } - if tm == -1 { - err = errors.New("极昼") - } - return tm, err -} - -/* - 晨朦影 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - angle,朦影角度:可选-6 -12 -18 -*/ -func MorningTwilightTime(jde, lon, lat, timezone, angle float64) (float64, error) { - var err error = nil - tm := basic.GetAsaTime(jde, lon, lat, timezone, angle) - if tm == -2 { - err = errors.New("不存在") - } - if tm == -1 { - err = errors.New("不存在") - } - return tm, err + calcJde := basic.GetSunTZTime(jde, lon, timezone) + return basic.JDE2Date(calcJde) } -/* - 昏朦影 - jde,世界时当地0时 JDE - lon,经度,东正西负 - lat,纬度,北正南负 - timezone,时区,东正西负 - angle,朦影角度:可选-6 -12 -18 -*/ -func EveningTwilightTime(jde, lon, lat, timezone, angle float64) (float64, error) { - var err error = nil - tm := basic.GetBanTime(jde, lon, lat, timezone, angle) - if tm == -2 { - err = errors.New("不存在") - } - if tm == -1 { - err = errors.New("不存在") - } - return tm, err +// EarthDistance 日地距离 +// 返回date对应UTC世界时日地距离 +func EarthDistance(date time.Time) float64 { + jde := basic.Date2JDE(date) + jde = basic.TD2UT(jde, true) + return basic.EarthAway(jde) }