Java根据经纬度获取日升日落时间
# 1.方法一:经纬度和日期计算 (日出、日落)
点击查看
SunTimesUtil:
public class SunTimesUtil {
static Double start = 0.0;
static Double end = 0.0;
static Double sRA = 0.0;
static Double sdec = 0.0;
static Double sr = 0.0;
static Double lon = 0.0;
public static void main(String[] args) throws ParseException {
//今天
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime());
System.out.println(getSunTimeAtDate(calendar.getTime(),120.2722222,30.333333333 ));
}
public static HashMap<String,Object> getSunTimeAtDate(Date d,Double longitude, Double latitude){
long xcts =Days_since_2000_Jan_0(d);
HashMap<String,Object> hm = new HashMap<>(2);
try {
hm = GetSunTime(xcts,longitude, latitude);
} catch (ParseException e) {
e.printStackTrace();
}
return hm;
}
public static HashMap<String,Object> GetSunTime(long day, Double longitude, Double latitude) throws ParseException
{
SunRiset(day, longitude, latitude, -35.0 / 60.0, 1,start,end);
String sunrise = ToLocalTime(start);
String sunset = ToLocalTime(end);
HashMap<String,Object> hm = new HashMap<>(2);
hm.put("sunRise",sunrise);
hm.put("sunSet",sunset);
return hm;
}
private static String ToLocalTime(Double utTime)
{
int hour = (int) (Math.floor(utTime));
Double temp = utTime - hour;
hour += 8;
temp = temp * 60;
int minute = (int) (Math.floor(temp));
String minuteStr = minute+" ";
if(minute<10){
minuteStr = "0"+minute;
}
return hour+":"+minuteStr;
}
private static void Sunpos(Double d, Double lon, Double r)
{
Double M,//太阳的平均近点角,从太阳观察到的地球(=从地球看到太阳的)距近日点(近地点)的角度。
w, //近日点的平均黄道经度。
e, //地球椭圆公转轨道离心率。
E, //太阳的偏近点角。计算公式见下面。
x, y,
v; //真近点角,太阳在任意时刻的真实近点角。
M = Revolution(356.0470 + 0.9856002585 * d);//自变量的组成:2000.0时刻太阳黄经为356.0470度,此后每天约推进一度(360度/365天
w = 282.9404 + 4.70935E-5 * d;//近日点的平均黄经。
e = 0.016709 - 1.151E-9 * d;//地球公转椭圆轨道离心率的时间演化。以上公式和黄赤交角公式一样,不必深究。
E = M + e * Radge * Sind(M) * (1.0 + e * Cosd(M));
x = Cosd(E) - e;
y = Math.sqrt(1.0 - e * e) * Sind(E);
setSr(Math.sqrt(x * x + y * y));
v = Atan2d(y, x);
lon = v + w;
setLon(lon);
if (lon >= 360.0)
{lon -= 360.0;
setLon(lon);}
}
private static void Sun_RA_dec(Double d, Double RA, Double dec, Double r)
{
Double obl_ecl, x, y, z;
Sunpos(d, lon, r);
//计算太阳的黄道坐标。
x = sr * Cosd(lon);
y = sr * Sind(lon);
//计算太阳的直角坐标。
obl_ecl = 23.4393 - 3.563E-7 * d;
//黄赤交角,同前。
z = y * Sind(obl_ecl);
y = y * Cosd(obl_ecl);
//把太阳的黄道坐标转换成赤道坐标(暂改用直角坐标)。
setsRA(Atan2d(y, x));
setSdec(Atan2d(z, Math.sqrt(x * x + y * y)));
//最后转成赤道坐标。显然太阳的位置是由黄道坐标方便地直接确定的,但必须转换到赤
//道坐标里才能结合地球的自转确定我们需要的白昼长度。
}
private static int SunRiset(long day, Double longitude, Double lat, Double altit, int upper_limb, Double trise, Double tset)
{
Double d, /* Days since 2000 Jan 0.0 (negative before) */
//以历元2000.0起算的日数。
sradius, /* Sun's apparent radius */
//太阳视半径,约16分(受日地距离、大气折射等诸多影响)
t, /* Diurnal arc */
//周日弧,太阳一天在天上走过的弧长。
tsouth, /* Time when Sun is at south */
sidtime; /* Local sidereal time */
//当地恒星时,即地球的真实自转周期。比平均太阳日(日常时间)长3分56秒。
int rc = 0; /* Return cde from function - usually 0 */
/* Compute d of 12h local mean solar time */
d = day/* Days_since_2000_Jan_0(date)*/ + 0.5 - longitude / 360.0;
//计算观测地当日中午时刻对应2000.0起算的日数。
/* Compute local sideral time of this moment */
sidtime = Revolution(GMST0(d) + 180.0 + longitude);
//计算同时刻的当地恒星时(以角度为单位)。以格林尼治为基准,用经度差校正。
/* Compute Sun's RA + Decl at this moment */
Sun_RA_dec(d, sRA,sdec,sr);
//计算同时刻太阳赤经赤纬。
/* Compute time when Sun is at south - in hours UT */
tsouth = 12.0 - Rev180(sidtime - sRA) / 15.0;
//计算太阳日的正午时刻,以世界时(格林尼治平太阳时)的小时计。
/* Compute the Sun's apparent radius, degrees */
sradius = 0.2666 / sr;
//太阳视半径。0.2666是一天文单位处的太阳视半径(角度)。
/* Do correction to upper limb, if necessary */
if (upper_limb != 0)
altit -= sradius;
//如果要用上边缘,就要扣除一个视半径。
/* Compute the diurnal arc that the Sun traverses to reach */
//计算周日弧。直接利用球面三角公式。如果碰到极昼极夜问题,同前处理。
/* the specified altitide altit: */
Double cost;
cost = (Sind(altit) - Sind(lat) * Sind(sdec)) /
(Cosd(lat) * Cosd(sdec));
if (cost >= 1.0)
{
rc = -1;
t = 0.0;
}
else
{
if (cost <= -1.0)
{
rc = +1;
t = 12.0; /* Sun always above altit */
}
else
t = Acosd(cost) / 15.0; /* The diurnal arc, hours */
}
/* Store rise and set times - in hours UT */
setStart(tsouth - t);
setEnd(tsouth + t);
return rc;
}
private static long Days_since_2000_Jan_0(Date date)
{
String d2000 = "2000-01-01";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Long ll = 0L;
try {
ll = date.getTime()-sdf.parse(d2000).getTime();
} catch (ParseException e) {
e.printStackTrace();
}
long day = ll/1000/60/60/24;
return day;
}
private static Double Revolution(Double x)
{
return (x - 360.0 * Math.floor(x * Inv360));
}
private static Double Rev180(Double x)
{
return (x - 360.0 * Math.floor(x * Inv360 + 0.5));
}
private static Double GMST0(Double d)
{
Double sidtim0;
sidtim0 = Revolution((180.0 + 356.0470 + 282.9404) +
(0.9856002585 + 4.70935E-5) * d);
return sidtim0;
}
private static Double Inv360 = 1.0 / 360.0;
private static Double Sind(Double x)
{
return Math.sin(x * Degrad);
}
private static Double Cosd(Double x)
{
return Math.cos(x * Degrad);
}
/* private static Double Tand(Double x)
{
return Math.tan(x * Degrad);
}
private static Double Atand(Double x)
{
return Radge * Math.atan(x);
}
private static Double Asind(Double x)
{
return Radge * Math.asin(x);
}*/
private static Double Acosd(Double x)
{
return Radge * Math.acos(x);
}
private static Double Atan2d(Double y, Double x)
{
return Radge * Math.atan2(y, x);
}
private static Double Radge = 180.0 / Math.PI;
private static Double Degrad = Math.PI / 180.0;
public static Double getStart() {
return start;
}
public static void setStart(Double start) {
SunTimesUtil.start = start;
}
public static Double getsRA() {
return sRA;
}
public static void setsRA(Double sRA) {
SunTimesUtil.sRA = sRA;
}
public static Double getSdec() {
return sdec;
}
public static void setSdec(Double sdec) {
SunTimesUtil.sdec = sdec;
}
public static Double getSr() {
return sr;
}
public static void setSr(Double sr) {
SunTimesUtil.sr = sr;
}
public static Double getLon() {
return lon;
}
public static void setLon(Double lon) {
SunTimesUtil.lon = lon;
}
public static Double getEnd() {
return end;
}
public static void setEnd(Double end) {
SunTimesUtil.end = end;
}
}
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# 2.方法二:经纬度和日期计算(日出、日落)
点击查看
SunRiseSet:
package com.rtmc.cloud.commons.utils.calculationSunriseAndSunsetTime;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SunRiseSet {
private static int[] days_of_month_1 = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private static int[] days_of_month_2 = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private final static double h = -0.833;//日出日落时太阳的位置
private final static double UTo = 180.0;//上次计算的日落日出时间,初始迭代值180.0
//输入日期
//输入经纬度
//判断是否为闰年:若为闰年,返回1;若不是闰年,返回0
public static boolean leap_year(int year) {
if (((year % 400 == 0) || (year % 100 != 0) && (year % 4 == 0))) return true;
else return false;
}
//求从格林威治时间公元2000年1月1日到计算日天数days
public static int days(int year, int month, int date) {
int i, a = 0;
for (i = 2000; i < year; i++) {
if (leap_year(i)) a = a + 366;
else a = a + 365;
}
if (leap_year(year)) {
for (i = 0; i < month - 1; i++) {
a = a + days_of_month_2[i];
}
} else {
for (i = 0; i < month - 1; i++) {
a = a + days_of_month_1[i];
}
}
a = a + date;
return a;
}
//求格林威治时间公元2000年1月1日到计算日的世纪数t
public static double t_century(int days, double UTo) {
return ((double) days + UTo / 360) / 36525;
}
//求太阳的平黄径
public static double L_sun(double t_century) {
return (280.460 + 36000.770 * t_century);
}
//求太阳的平近点角
public static double G_sun(double t_century) {
return (357.528 + 35999.050 * t_century);
}
//求黄道经度
public static double ecliptic_longitude(double L_sun, double G_sun) {
return (L_sun + 1.915 * Math.sin(G_sun * Math.PI / 180) + 0.02 * Math.sin(2 * G_sun * Math.PI / 180));
}
//求地球倾角
public static double earth_tilt(double t_century) {
return (23.4393 - 0.0130 * t_century);
}
//求太阳偏差
public static double sun_deviation(double earth_tilt, double ecliptic_longitude) {
return (180 / Math.PI * Math.asin(Math.sin(Math.PI / 180 * earth_tilt) * Math.sin(Math.PI / 180 * ecliptic_longitude)));
}
//求格林威治时间的太阳时间角GHA
public static double GHA(double UTo, double G_sun, double ecliptic_longitude) {
return (UTo - 180 - 1.915 * Math.sin(G_sun * Math.PI / 180) - 0.02 * Math.sin(2 * G_sun * Math.PI / 180) + 2.466 * Math.sin(2 * ecliptic_longitude * Math.PI / 180) - 0.053 * Math.sin(4 * ecliptic_longitude * Math.PI / 180));
}
//求修正值e
public static double e(double h, double glat, double sun_deviation) {
return 180 / Math.PI * Math.acos((Math.sin(h * Math.PI / 180) - Math.sin(glat * Math.PI / 180) * Math.sin(sun_deviation * Math.PI / 180)) / (Math.cos(glat * Math.PI / 180) * Math.cos(sun_deviation * Math.PI / 180)));
}
//求日出时间
public static double UT_rise(double UTo, double GHA, double glong, double e) {
return (UTo - (GHA + glong + e));
}
//求日落时间
public static double UT_set(double UTo, double GHA, double glong, double e) {
return (UTo - (GHA + glong - e));
}
//判断并返回结果(日出)
public static double result_rise(double UT, double UTo, double glong, double glat, int year, int month, int date) {
double d;
if (UT >= UTo) d = UT - UTo;
else d = UTo - UT;
if (d >= 0.1) {
UTo = UT;
UT = UT_rise(UTo,
GHA(UTo, G_sun(t_century(days(year, month, date), UTo)),
ecliptic_longitude(L_sun(t_century(days(year, month, date), UTo)),
G_sun(t_century(days(year, month, date), UTo)))),
glong,
e(h, glat, sun_deviation(earth_tilt(t_century(days(year, month, date), UTo)),
ecliptic_longitude(L_sun(t_century(days(year, month, date), UTo)),
G_sun(t_century(days(year, month, date), UTo))))));
result_rise(UT, UTo, glong, glat, year, month, date);
}
return UT;
}
//判断并返回结果(日落)
public static double result_set(double UT, double UTo, double glong, double glat, int year, int month, int date) {
double d;
if (UT >= UTo) d = UT - UTo;
else d = UTo - UT;
if (d >= 0.1) {
UTo = UT;
UT = UT_set(UTo,
GHA(UTo, G_sun(t_century(days(year, month, date), UTo)),
ecliptic_longitude(L_sun(t_century(days(year, month, date), UTo)),
G_sun(t_century(days(year, month, date), UTo)))),
glong,
e(h, glat, sun_deviation(earth_tilt(t_century(days(year, month, date), UTo)),
ecliptic_longitude(L_sun(t_century(days(year, month, date), UTo)),
G_sun(t_century(days(year, month, date), UTo))))));
result_set(UT, UTo, glong, glat, year, month, date);
}
return UT;
}
//求时区
public static int Zone(double glong) {
if (glong >= 0) return (int) ((int) (glong / 15.0) + 1);
else return (int) ((int) (glong / 15.0) - 1);
}
//打印结果
// public static void output(double rise, double set, double glong){
// if((int)(60*(rise/15+Zone(glong)-(int)(rise/15+Zone(glong))))<10)
// System.out.println("The time at which the sunrise is: "+(int)(rise/15+Zone(glong))+":"+(int)(60*(rise/15+Zone(glong)-(int)(rise/15+Zone(glong))))+" .\n");
// else System.out.println("The time at which the sunrise is: "+(int)(rise/15+Zone(glong))+":"+(int)(60*(rise/15+Zone(glong)-(int)(rise/15+Zone(glong))))+" .\n");
//
// if((int)(60*(set/15+Zone(glong)-(int)(set/15+Zone(glong))))<10)
// System.out.println("The time at which the sunset is: "+(int)(set/15+Zone(glong))+": "+(int)(60*(set/15+Zone(glong)-(int)(set/15+Zone(glong))))+" .\n");
// else System.out.println("The time at which the sunset is: "+(int)(set/15+Zone(glong))+":"+(int)(60*(set/15+Zone(glong)-(int)(set/15+Zone(glong))))+" .\n");
// }
public static String getSunrise(BigDecimal longitude, BigDecimal latitude, Date sunTime) {
if (sunTime != null && longitude != null && latitude != null) {
double sunrise, glong, glat;
int year, month, date;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateTime = sdf.format(sunTime);
String[] rq = dateTime.split("-");
String y = rq[0];
String m = rq[1];
String d = rq[2];
year = Integer.parseInt(y);
if (m != null && m != "" && m.indexOf("0") == -1) {
m = m.replaceAll("0", "");
}
month = Integer.parseInt(m);
date = Integer.parseInt(d);
glong = longitude.doubleValue();
glat = latitude.doubleValue();
sunrise = result_rise(UT_rise(UTo,
GHA(UTo, G_sun(t_century(days(year, month, date), UTo)),
ecliptic_longitude(L_sun(t_century(days(year, month, date), UTo)),
G_sun(t_century(days(year, month, date), UTo)))),
glong,
e(h, glat, sun_deviation(earth_tilt(t_century(days(year, month, date), UTo)),
ecliptic_longitude(L_sun(t_century(days(year, month, date), UTo)),
G_sun(t_century(days(year, month, date), UTo)))))), UTo, glong, glat, year, month, date);
//System.out.println("Sunrise is: "+(int)(sunrise/15+Zone(glong))+":"+(int)(60*(sunrise/15+Zone(glong)-(int)(sunrise/15+Zone(glong))))+" .\n");
// Log.d("Sunrise", "Sunrise is: "+(int)(sunrise/15+8)+":"+(int)(60*(sunrise/15+8-(int)(sunrise/15+8)))+" .\n");
//return "Sunrise is: "+(int)(sunrise/15+Zone(glong))+":"+(int)(60*(sunrise/15+Zone(glong)-(int)(sunrise/15+Zone(glong))))+" .\n";
return (int) (sunrise / 15 + 8) + ":" + (int) (60 * (sunrise / 15 + 8 - (int) (sunrise / 15 + 8)));
}
return null;
}
public static String getSunset(BigDecimal longitude, BigDecimal latitude, Date sunTime) {
if (sunTime != null && latitude != null && longitude != null) {
double sunset, glong, glat;
int year, month, date;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateTime = sdf.format(sunTime);
String[] rq = dateTime.split("-");
String y = rq[0];
String m = rq[1];
String d = rq[2];
year = Integer.parseInt(y);
if (m != null && m != "" && m.indexOf("0") == -1) {
m = m.replaceAll("0", "");
}
month = Integer.parseInt(m);
date = Integer.parseInt(d);
glong = longitude.doubleValue();
glat = latitude.doubleValue();
sunset = result_set(UT_set(UTo,
GHA(UTo, G_sun(t_century(days(year, month, date), UTo)),
ecliptic_longitude(L_sun(t_century(days(year, month, date), UTo)),
G_sun(t_century(days(year, month, date), UTo)))),
glong,
e(h, glat, sun_deviation(earth_tilt(t_century(days(year, month, date), UTo)),
ecliptic_longitude(L_sun(t_century(days(year, month, date), UTo)),
G_sun(t_century(days(year, month, date), UTo)))))), UTo, glong, glat, year, month, date);
//System.out.println("The time at which the sunset is: "+(int)(sunset/15+Zone(glong))+":"+(int)(60*(sunset/15+Zone(glong)-(int)(sunset/15+Zone(glong))))+" .\n");
// Log.d("Sunset", "Sunset is: "+(int)(sunset/15+8)+":"+(int)(60*(sunset/15+8-(int)(sunset/15+8)))+" .\n");
//return "Sunset is: "+(int)(sunset/15+Zone(glong))+":"+(int)(60*(sunset/15+Zone(glong)-(int)(sunset/15+Zone(glong))))+" .\n";
return (int) (sunset / 15 + 8) + ":" + (int) (60 * (sunset / 15 + 8 - (int) (sunset / 15 + 8)));
}
return null;
}
public static void main(String[] args) {
String str1 = SunRiseSet.getSunrise(new BigDecimal(104.066507),new BigDecimal(30.625124),new Date());
String str2 = SunRiseSet.getSunset(new BigDecimal(104.066507),new BigDecimal(30.625124),new Date());
System.out.println("日出时间:" + str1);
System.out.println("日落时间:" + str2);
}
}
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# 3.方法三:儒略日算法(日出、日落、日中)
点击查看
DayTime:
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class DayTime {
private static Properties propt;
private static double RAD = 180.0 * 3600 / Math.PI;
private static double midDayTime;
private static double dawnTime;
private static String codeStr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static {
propt = new Properties();
try {
propt.load(DayTime.class.getClassLoader().getResourceAsStream("jwd.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
@SuppressWarnings("deprecation")
public static Map<DayTimeType, String> dailytime(String area) {
Date date = new Date();
return dailytime(area, date.getYear(), date.getMonth(), date.getDay(), 0, 0, 0,8.0);
}
public static Map<DayTimeType, String> dailytime(String area, int year, int month, int day, int hour, int min, int sec,double tz) {
Map<DayTimeType, String> map = new HashMap<DayTimeType, String>();
String jwd = decodeJWD(area);
System.out.println(jwd);
Double wd = (Double.parseDouble(jwd.substring(0, 2)) + Double.parseDouble(jwd.substring(2, 4)) / 60) / 180 * Math.PI;
Double jd = -(Double.parseDouble(jwd.substring(4, 7)) + Double.parseDouble(jwd.substring(7)) / 60) / 180 * Math.PI;
double richu = timeToDouble(year, month, day, hour, min, sec) - 2451544.5;
for (int i = 0; i < 10; i++)
richu = sunRiseTime(richu, jd, wd, tz / 24);// 逐步逼近法算10次
// 日出
map.put(DayTimeType.SUNRISE, doubleToStr(richu));
// 日落
map.put(DayTimeType.SUNSET, doubleToStr(midDayTime + midDayTime - richu));
// 中天
map.put(DayTimeType.MIDTIME, doubleToStr(midDayTime));
// 天亮
map.put(DayTimeType.DAWNTIME, doubleToStr(dawnTime));
// 天黑
map.put(DayTimeType.NIGHTTIME, doubleToStr(midDayTime + midDayTime - dawnTime));
// 昼长
map.put(DayTimeType.DAYTIME, doubleToStr((midDayTime - dawnTime) * 2 - 0.5));
return map;
}
// 加密
public static String decodeJWD(String encode) {
StringBuilder jwd = new StringBuilder();
for (int i = 0; i < 4; i++)
if (2 == i)
jwd.append(String.format("%03d", codeStr.indexOf(encode.charAt(i)) + 73));
else
jwd.append(String.format("%02d", codeStr.indexOf(encode.charAt(i))));
return jwd.toString();
}
// 解密
public static String encodeJWD(Integer decode) {
StringBuilder jwd = new StringBuilder();
int i = 230811316;
int ge = i % 100;
int shi = i % 100000 - ge;
int bai = i % 10000000 - shi;
int qian = i % 1000000000 - bai;
shi = shi / 100 - 73;
bai = bai / 100000;
qian = qian / 10000000;
jwd.append(codeStr.charAt(qian)).append(codeStr.charAt(bai)).append(codeStr.charAt(shi)).append(codeStr.charAt(ge));
return jwd.toString();
}
/**
*
* @param date
* 儒略日平午
* @param lo
* 地理经度
* @param la
* 地理纬度
* @param tz
* 时区
* @return 太阳升起时间
*/
public static Double sunRiseTime(double date, double lo, double la, double tz) {
date = date - tz;
// 太阳黄经以及它的正余弦值
double t = date / 36525;
double j = sunHJ(t);
// 太阳黄经以及它的正余弦值
double sinJ = Math.sin(j);
double cosJ = Math.cos(j);
// 其中2*PI*(0.7790572732640 + 1.00273781191135448*jd)恒星时(子午圈位置)
double gst = 2 * Math.PI * (0.779057273264 + 1.00273781191135 * date) + (0.014506 + 4612.15739966 * t + 1.39667721 * t * t) / RAD;
double E = (84381.406 - 46.836769 * t) / RAD; // 黄赤交角
double a = Math.atan2(sinJ * Math.cos(E), cosJ);// '太阳赤经
double D = Math.asin(Math.sin(E) * sinJ); // 太阳赤纬
double cosH0 = (Math.sin(-50 * 60 / RAD) - Math.sin(la) * Math.sin(D)) / (Math.cos(la) * Math.cos(D)); // 日出的时角计算,地平线下50分
double cosH1 = (Math.sin(-6 * 3600 / RAD) - Math.sin(la) * Math.sin(D)) / (Math.cos(la) * Math.cos(D)); // 天亮的时角计算,地平线下6度,若为航海请改为地平线下12度
// 严格应当区分极昼极夜,本程序不算
if (cosH0 >= 1 || cosH0 <= -1)
return -0.5;// 极昼
double H0 = -Math.acos(cosH0); // 升点时角(日出)若去掉负号 就是降点时角,也可以利用中天和升点计算
double H1 = -Math.acos(cosH1);
double H = gst - lo - a; // 太阳时角
midDayTime = date - degree(H) / Math.PI / 2 + tz; // 中天时间
dawnTime = date - degree(H - H1) / Math.PI / 2 + tz;// 天亮时间
return date - degree(H - H0) / Math.PI / 2 + tz; // 日出时间,函数返回值
}
/**
* 保证角度∈(-π,π)
*
* @param ag
* @return ag
*/
public static Double degree(double ag) {
ag = mod(ag, 2 * Math.PI);
return ag <= -Math.PI ? ag + 2 * Math.PI : ag > Math.PI ? ag - 2 * Math.PI : ag;
}
public static Double mod(double num1, double num2) {
num2 = Math.abs(num2);
// 只是取决于Num1的符号
return num1 >= 0 ? num1 - ((int) (num1 / num2)) * num2 : ((int) (Math.abs(num1) / num2)) * num2 - Math.abs(num1);
}
/**
* @param t
* 儒略世纪数
* @return 太阳黄经
*/
public static Double sunHJ(double t) {
t = t + (32.0 * (t + 1.8) * (t + 1.8) - 20) / 86400.0 / 36525.0;
// 儒略世纪年数,力学时
double j = 48950621.66 + 6283319653.318 * t + 53 * t * t - 994 + 334166 * Math.cos(4.669257 + 628.307585 * t) + 3489 * Math.cos(4.6261 + 1256.61517 * t) + 2060.6 * Math.cos(2.67823 + 628.307585 * t) * t;
return j / 10000000;
}
/**
* 儒略日的计算
*
* @param y
* 年
* @param M
* 月
* @param d
* 日
* @param h
* 小时
* @param m
* 分
* @param s
* 秒
* @return int
*/
public static int timeToDouble(int y, int M, int d, int h, int m, int s) {
double time = 0;
if (M <= 2) {
M += 12;
y -= 1;
}
if (y * 372 + M * 31 + d >= 588829) {
time = (int) (y / 100);
time = 2 - time + (int) (time / 4);
}
time += (int) Math.round(365.25 * (y + 4716) + 0.01) + (int) (30.60001 * (M + 1)) + d + (h * 3600 + m * 60 + s) / (24 * 3600) - 1524.5;
return (int) Math.round(time);
}
public static String doubleToStr(double time) {
double t = time + 0.5;
t = (t - (int) t) * 24;
int h = (int) t;
t = (t - h) * 60;
int m = (int) t;
t = (t - m) * 60;
int s = (int) t;
return h + ":" + m + ":" + s;
}
public static void main(String[] args) {
// System.out.println(decodeJWD("N3dS肇庆"));
// String jwd = decodeJWD("N3dS肇庆");
// Double wd = (Double.parseDouble(jwd.substring(0, 2)) +
// Double.parseDouble(jwd.substring(2, 4)) / 60) / 180 * Math.PI;
// Double jd = -(Double.parseDouble(jwd.substring(4, 7)) +
// Double.parseDouble(jwd.substring(7)) / 60) / 180 * Math.PI;
// double richu = timeToDouble(2012, 6, 25, 0, 0, 0) - 2451544.5;
// System.out.println(richu + " " + timeToDouble(2012, 6, 25, 0, 0, 0));
// richu = sunRiseTime(richu, jd, wd, 8.0 / 24);
// System.out.println(richu);
// richu = sunRiseTime(richu, jd, wd, 8.0 / 24);// 逐步逼近法算两次
// System.out.println(doubleToStr(richu));
String t = "03";
System.out.println(Integer.parseInt(t));
System.out.println(propt.getProperty("HI"));
String[] strs = propt.getProperty("HI").split(" ");
for (int i = 1; i < strs.length; i++) {
System.out.println(strs[i] + " 日出 " + dailytime(strs[i]).get(DayTimeType.SUNRISE));
System.out.println(strs[i] + " 日落" + dailytime(strs[i]).get(DayTimeType.SUNSET));
System.out.println(strs[i] + " 中天" + dailytime(strs[i]).get(DayTimeType.MIDTIME));
System.out.println(strs[i] + " 天亮" + dailytime(strs[i]).get(DayTimeType.DAWNTIME));
System.out.println(strs[i] + " 天黑" + dailytime(strs[i]).get(DayTimeType.NIGHTTIME));
System.out.println(strs[i] + " 昼长" + dailytime(strs[i]).get(DayTimeType.DAYTIME));
}
System.out.println(encodeJWD(230811316));
}
}
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
枚举类型:
public enum DayTimeType { SUNRISE, SUNSET, MIDTIME, DAWNTIME, NIGHTTIME, DAYTIME}
1
编辑 (opens new window)
上次更新: 2022/03/02, 13:58:17