Java获取当地的日出日落时间代码分享
根据经纬度和当前日期获取当地的日出日落时间,强大的google搜索让我迅速找到了一个外国人写的一个java类,代码中的注释写得很清楚。
这里直接贴出代码来:
/******************************************************************************
*
* sunrisesunset.java
*
*******************************************************************************
*
* java class: sunrisesunset
*
* this java class is part of a collection of classes developed for the
* reading and processing of oceanographic and meterological data collected
* since 1970 by environmental buoys and stations. this dataset is
* maintained by the national oceanographic data center and is publicly
* available. these java classes were written for the us environmental
* protection agency's national exposure research laboratory under contract
* no. gs-10f-0073k with neptune and company of los alamos, new mexico.
*
* purpose:
*
* this java class performs calculations to determine the time of
* sunrise and sunset given lat, long, and date.
*
* inputs:
*
* latitude, longitude, date/time, and time zone.
*
* outputs:
*
* local time of sunrise and sunset as calculated by the
* program.
* if no sunrise or no sunset occurs, or if the sun is up all day
* or down all day, appropriate boolean values are set.
* a boolean is provided to identify if the time provided is during the day.
*
* the above values are accessed by the following methods:
*
* date getsunrise() returns date/time of sunrise
* date getsunset() returns date/time of sunset
* boolean issunrise() returns true if there was a sunrise, else false
* boolean issunset() returns true if there was a sunset, else false
* boolean issunup() returns true if sun is up all day, else false
* boolean issundown() returns true if sun is down all day, else false
* boolean isdaytime() returns true if sun is up at the time
* specified, else false
*
* required classes from the java library:
*
* java.util.date
* java.text.simpledateformat
* java.text.parseexception;
* java.math.bigdecimal;
*
* package of which this class is a member:
*
* default
*
* known limitations:
*
* it is assumed that the data provided are within valie ranges
* (i.e. latitude between -90 and +90, longitude between 0 and 360,
* a valid date, and time zone between -14 and +14.
*
* compatibility:
*
* java 1.1.8
*
* references:
*
* the mathematical algorithms used in this program are patterned
* after those debveloped by roger sinnott in his basic program,
* sunup.bas, published in sky & telescope magazine:
* sinnott, roger w. "sunrise and sunset: a challenge"
* sky & telescope, august, 1994 p.84-85
*
* the following is a cross-index of variables used in sunup.bas.
* a single definition from multiple reuse of variable names in
* sunup.bas was clarified with various definitions in this program.
*
* sunup.bas this class
*
* a dfa
* a(2) dfaa1, dfaa2
* a0 dfa0
* a2 dfa2
* a5 dfa5
* az not used
* c dfcoslat
* c0 dfc0
* d iday
* d(2) dfdd1, dfdd2
* d0 dfd0
* d1 dfd1
* d2 dfd2
* d5 dfd5
* d7 not used
* da dfda
* dd dfdd
* g bgregorian, dfgg
* h dftimezone
* h0 dfh0
* h1 dfh1
* h2 dfh2
* h3 dfhourrise, dfhourset
* h7 not used
* j dfj
* j3 dfj3
* k1 dfk1
* l dfll
* l0 dfl0
* l2 dfl2
* l5 dflon
* m imonth
* m3 dfminrise, dfminset
* n7 not used
* p dfp
* s isign, dfsinlat, dfss
* t dft
* t0 dft0
* t3 not used
* tt dftt
* u dfuu
* v dfvv
* v0 dfv0
* v1 dfv1
* v2 dfv2
* w dfww
* y iyear
* z dfzenith
* z0 dftimezone
*
*
* author/company:
*
* jdt: john tauxe, neptune and company
* jmg: jo marie green
*
* change log:
*
* date ver by description of change
* _________ _____ ___ ______________________________________________
* 5 jan 01 0.006 jdt excised from ssapp.java v. 0.005.
* 11 jan 01 0.007 jdt minor modifications to comments based on
* material from sinnott, 1994.
* 7 feb 01 0.008 jdt fixed backwards time zone. the standard is that
* local time zone is specified in hours east of
* greenwich, so that est would be -5, for example.
* for some reason, sunup.bas does this backwards
* (probably an americocentric perspective) and
* sunrisesunset adopted that convention. oops.
* so the sign in the math is changed.
* 7 feb 01 0.009 jdt well, that threw off the azimuth calculation...
* removed the azimuth calculations.
* 14 feb 01 0.010 jdt added ability to accept a time (hh:mm) in
* dateinput, and decide if that time is daytime
* or nighttime.
* 27 feb 01 0.011 jdt added accessor methods in place of having public
* variables to get results.
* 28 feb 01 0.012 jdt cleaned up list of imported classes.
* 28 mar 01 1.10 jdt final version accompanying deliverable 1b.
* 4 apr 01 1.11 jdt moved logic supporting .isdaytime into method.
* moved calculations out of constructor.
* 01 may 01 1.12 jmg added 'gmt' designation and testing lines.
* 16 may 01 1.13 jdt added setlenient( false ) and settimezone( tz )
* to dfmtday, dfmtmonth, and dfmtyear in
* docalculations.
* 27 jun 01 1.14 jdt removed reliance on stationconstants (gmt).
* 13 aug 01 1.20 jdt final version accompanying deliverable 1c.
* 6 sep 01 1.21 jdt thorough code and comment review.
* 21 sep 01 1.30 jdt final version accompanying deliverable 2.
* 17 dec 01 1.40 jdt version accompanying final deliverable.
*
*----------------------------------------------------------------------------*/
// import required classes and packages
import java.util.date;
import java.text.simpledateformat;
import java.text.parseexception;
import java.math.bigdecimal;
import java.util.timezone;
/******************************************************************************
* class: sunrisesunset class
*******************************************************************************
*
* this java class performs calculations to determine the time of
* sunrise and sunset given lat, long, and date.
*
* it is assumed that the data provided are within valie ranges
* (i.e. latitude between -90 and +90, longitude between 0 and 360,
* a valid date, and time zone between -14 and +14.
*
*----------------------------------------------------------------------------*/
public class sunrisesunset
{
// declare and initialize variables
private double dflat; // latitude from user
private double dflon; // latitude from user
private date dateinput; // date/time from user
private double dftimezone; // time zone from user
private date datesunrise; // date and time of sunrise
private date datesunset; // date and time of sunset
private boolean bsunrisetoday = false; // flag for sunrise on this date
private boolean bsunsettoday = false; // flag for sunset on this date
private boolean bsunupallday = false; // flag for sun up all day
private boolean bsundownallday = false; // flag for sun down all day
private boolean bdaytime = false; // flag for daytime, given
// hour and min in dateinput
private boolean bsunrise = false; // sunrise during hour checked
private boolean bsunset = false; // sunset during hour checked
private boolean bgregorian = false; // flag for gregorian calendar
private int ijulian; // julian day
private int iyear; // year of date of interest
private int imonth; // month of date of interest
private int iday; // day of date of interest
private int icount; // a simple counter
private int isign; // sunup.bas: s
private double dfhourrise, dfhourset; // hour of event: sunup.bas h3
private double dfminrise, dfminset; // minute of event: sunup.bas m3
private double dfsinlat, dfcoslat; // sin and cos of latitude
private double dfzenith; // sunup.bas z: zenith
private simpledateformat dfmtdate; // formatting for date alone
private simpledateformat dfmtdatetime; // formatting for date and time
private simpledateformat dfmtyear; // formatting for year
private simpledateformat dfmtmonth; // formatting for month
private simpledateformat dfmtday; // formatting for day
// many variables in sunup.bas have undocumented meanings,
// and so are translated rather directly to avoid confusion:
private double dfaa1 = 0, dfaa2 = 0; // sunup.bas a(2)
private double dfdd1 = 0, dfdd2 = 0; // sunup.bas d(2)
private double dfc0; // sunup.bas c0
private double dfk1; // sunup.bas k1
private double dfp; // sunup.bas p
private double dfj; // sunup.bas j
private double dfj3; // sunup.bas j3
private double dfa; // sunup.bas a
private double dfa0, dfa2, dfa5; // sunup.bas a0, a2, a5
private double dfd0, dfd1, dfd2, dfd5; // sunup.bas d0, d1, d2, d5
private double dfda, dfdd; // sunup.bas da, dd
private double dfh0, dfh1, dfh2; // sunup.bas h0, h1, h2
private double dfl0, dfl2; // sunup.bas l0, l2
private double dft, dft0, dftt; // sunup.bas t, t0, tt
private double dfv0, dfv1, dfv2; // sunup.bas v0, v1, v2
private timezone tz = timezone.gettimezone( "gmt" );
/******************************************************************************
* method: sunrisesunset
*******************************************************************************
*
* constructor for sunrisesunset class.
*
*----------------------------------------------------------------------------*/
sunrisesunset(
double dflatin, // latitude
double dflonin, // longitude
date dateinputin, // date
double dftimezonein // time zone
)
{
// copy values supplied as agruments to local variables.
dflat = dflatin;
dflon = dflonin;
dateinput = dateinputin;
dftimezone = dftimezonein;
// call the method to do the calculations.
docalculations();
} // end of class constructor
/******************************************************************************
* method: docalculations
*******************************************************************************
*
* method for performing the calculations done in sunup.bas.
*
*----------------------------------------------------------------------------*/
private void docalculations()
{
try
{
// break out day, month, and year from date provided.
// (this is necesary for the math algorithms.)
dfmtyear = new simpledateformat( "yyyy" );
dfmtyear.setlenient( false );
dfmtyear.settimezone( tz );
dfmtmonth = new simpledateformat( "m" );
dfmtmonth.setlenient( false );
dfmtmonth.settimezone( tz );
dfmtday = new simpledateformat( "d" );
dfmtday.setlenient( false );
dfmtday.settimezone( tz );
iyear = integer.parseint( dfmtyear.format( dateinput ) );
imonth = integer.parseint( dfmtmonth.format( dateinput ) );
iday = integer.parseint( dfmtday.format( dateinput ) );
// convert time zone hours to decimal days (sunup.bas line 50)
dftimezone = dftimezone / 24.0;
// note: (7 feb 2001) here is a non-standard part of sunup.bas:
// it (and this algorithm) assumes that the time zone is
// positive west, instead of the standard negative west.
// classes calling sunrisesunset will be assuming that
// times zones are specified in negative west, so here the
// sign is changed so that the sunup algorithm works:
dftimezone = -dftimezone;
// convert longitude to fraction (sunup.bas line 50)
dflon = dflon / 360.0;
// convert calendar date to julian date:
// check to see if it's later than 1583: gregorian calendar
// when declared, bgregorian is initialized to false.
// ** consider making a separate class of this function. **
if( iyear >= 1583 ) bgregorian = true;
// sunup.bas 1210
dfj = -math.floor( 7.0 // sunup used int, not floor
* ( math.floor(
( imonth + 9.0 )
/ 12.0
) + iyear
) / 4.0
)
// add sunup.bas 1240 and 1250 for g = 0
+ math.floor( imonth * 275.0 / 9.0 )
+ iday
+ 1721027.0
+ iyear * 367.0;
if ( bgregorian )
{
// sunup.bas 1230
if ( ( imonth - 9.0 ) < 0.0 ) isign = -1;
else isign = 1;
dfa = math.abs( imonth - 9.0 );
// sunup.bas 1240 and 1250
dfj3 = -math.floor(
(
math.floor(
math.floor( iyear
+ (double)isign
* math.floor( dfa / 7.0 )
)
/ 100.0
) + 1.0
) * 0.75
);
// correct dfj as in sunup.bas 1240 and 1250 for g = 1
dfj = dfj + dfj3 + 2.0;
}
// sunup.bas 1290
ijulian = (int)dfj - 1;
// sunup.bas 60 and 70 (see also line 1290)
dft = (double)ijulian - 2451545.0 + 0.5;
dftt = dft / 36525.0 + 1.0; // centuries since 1900
// calculate local sidereal time at 0h in zone time
// sunup.bas 410 through 460
dft0 = ( dft * 8640184.813 / 36525.0
+ 24110.5
+ dftimezone * 86636.6
+ dflon * 86400.0
)
/ 86400.0;
dft0 = dft0 - math.floor( dft0 ); // note: sunup.bas uses int()
dft0 = dft0 * 2.0 * math.pi;
// sunup.bas 90
dft = dft + dftimezone;
// sunup.bas 110: get sun's position
for( icount=0; icount<=1; icount++ ) // loop thru only twice
{
// calculate sun's right ascension and declination
// at the start and end of each day.
// sunup.bas 910 - 1160: fundamental arguments
// from van flandern and pulkkinen, 1979
// declare local temporary doubles for calculations
double dfgg; // sunup.bas g
double dfll; // sunup.bas l
double dfss; // sunup.bas s
double dfuu; // sunup.bas u
double dfvv; // sunup.bas v
double dfww; // sunup.bas w
dfll = 0.779072 + 0.00273790931 * dft;
dfll = dfll - math.floor( dfll );
dfll = dfll * 2.0 * math.pi;
dfgg = 0.993126 + 0.0027377785 * dft;
dfgg = dfgg - math.floor( dfgg );
dfgg = dfgg * 2.0 * math.pi;
dfvv = 0.39785 * math.sin( dfll )
- 0.01000 * math.sin( dfll - dfgg )
+ 0.00333 * math.sin( dfll + dfgg )
- 0.00021 * math.sin( dfll ) * dftt;
dfuu = 1
- 0.03349 * math.cos( dfgg )
- 0.00014 * math.cos( dfll * 2.0 )
+ 0.00008 * math.cos( dfll );
dfww = - 0.00010
- 0.04129 * math.sin( dfll * 2.0 )
+ 0.03211 * math.sin( dfgg )
- 0.00104 * math.sin( 2.0 * dfll - dfgg )
- 0.00035 * math.sin( 2.0 * dfll + dfgg )
- 0.00008 * math.sin( dfgg ) * dftt;
// compute sun's ra and dec; sunup.bas 1120 - 1140
dfss = dfww / math.sqrt( dfuu - dfvv * dfvv );
dfa5 = dfll
+ math.atan( dfss / math.sqrt( 1.0 - dfss * dfss ));
dfss = dfvv / math.sqrt( dfuu );
dfd5 = math.atan( dfss / math.sqrt( 1 - dfss * dfss ));
// set values and increment t
if ( icount == 0 ) // sunup.bas 125
{
dfaa1 = dfa5;
dfdd1 = dfd5;
}
else // sunup.bas 145
{
dfaa2 = dfa5;
dfdd2 = dfd5;
}
dft = dft + 1.0; // sunup.bas 130
} // end of get sun's position for loop
if ( dfaa2 < dfaa1 ) dfaa2 = dfaa2 + 2.0 * math.pi;
// sunup.bas 150
dfzenith = math.pi * 90.833 / 180.0; // sunup.bas 160
dfsinlat = math.sin( dflat * math.pi / 180.0 ); // sunup.bas 170
dfcoslat = math.cos( dflat * math.pi / 180.0 ); // sunup.bas 170
dfa0 = dfaa1; // sunup.bas 190
dfd0 = dfdd1; // sunup.bas 190
dfda = dfaa2 - dfaa1; // sunup.bas 200
dfdd = dfdd2 - dfdd1; // sunup.bas 200
dfk1 = 15.0 * 1.0027379 * math.pi / 180.0; // sunup.bas 330
// initialize sunrise and sunset times, and other variables
// hr and min are set to impossible times to make errors obvious
dfhourrise = 99.0;
dfminrise = 99.0;
dfhourset = 99.0;
dfminset = 99.0;
dfv0 = 0.0; // initialization implied by absence in sunup.bas
dfv2 = 0.0; // initialization implied by absence in sunup.bas
// test each hour to see if the sun crosses the horizon
// and which way it is heading.
for( icount=0; icount<24; icount++ ) // sunup.bas 210
{
double tempa; // sunup.bas a
double tempb; // sunup.bas b
double tempd; // sunup.bas d
double tempe; // sunup.bas e
dfc0 = (double)icount;
dfp = ( dfc0 + 1.0 ) / 24.0; // sunup.bas 220
dfa2 = dfaa1 + dfp * dfda; // sunup.bas 230
dfd2 = dfdd1 + dfp * dfdd; // sunup.bas 230
dfl0 = dft0 + dfc0 * dfk1; // sunup.bas 500
dfl2 = dfl0 + dfk1; // sunup.bas 500
dfh0 = dfl0 - dfa0; // sunup.bas 510
dfh2 = dfl2 - dfa2; // sunup.bas 510
// hour angle at half hour
dfh1 = ( dfh2 + dfh0 ) / 2.0; // sunup.bas 520
// declination at half hour
dfd1 = ( dfd2 + dfd0 ) / 2.0; // sunup.bas 530
// set value of dfv0 only if this is the first hour,
// otherwise, it will get set to the last dfv2 (sunup.bas 250)
if ( icount == 0 ) // sunup.bas 550
{
dfv0 = dfsinlat * math.sin( dfd0 )
+ dfcoslat * math.cos( dfd0 ) * math.cos( dfh0 )
- math.cos( dfzenith ); // sunup.bas 560
}
else
dfv0 = dfv2; // that is, dfv2 from the previous hour.
dfv2 = dfsinlat * math.sin( dfd2 )
+ dfcoslat * math.cos( dfd2 ) * math.cos( dfh2 )
- math.cos( dfzenith ); // sunup.bas 570
// if dfv0 and dfv2 have the same sign, then proceed to next hr
if (
( dfv0 >= 0.0 && dfv2 >= 0.0 ) // both are positive
|| // or
( dfv0 < 0.0 && dfv2 < 0.0 ) // both are negative
)
{
// break iteration and proceed to test next hour
dfa0 = dfa2; // sunup.bas 250
dfd0 = dfd2; // sunup.bas 250
continue; // sunup.bas 610
}
dfv1 = dfsinlat * math.sin( dfd1 )
+ dfcoslat * math.cos( dfd1 ) * math.cos( dfh1 )
- math.cos( dfzenith ); // sunup.bas 590
tempa = 2.0 * dfv2 - 4.0 * dfv1 + 2.0 * dfv0;
// sunup.bas 600
tempb = 4.0 * dfv1 - 3.0 * dfv0 - dfv2; // sunup.bas 600
tempd = tempb * tempb - 4.0 * tempa * dfv0; // sunup.bas 610
if ( tempd < 0.0 )
{
// break iteration and proceed to test next hour
dfa0 = dfa2; // sunup.bas 250
dfd0 = dfd2; // sunup.bas 250
continue; // sunup.bas 610
}
tempd = math.sqrt( tempd ); // sunup.bas 620
// determine occurence of sunrise or sunset.
// flags to identify occurrence during this day are
// bsunrisetoday and bsunsettoday, and are initialized false.
// these are set true only if sunrise or sunset occurs
// at any point in the hourly loop. never set to false.
// flags to identify occurrence during this hour:
bsunrise = false; // reset before test
bsunset = false; // reset before test
if ( dfv0 < 0.0 && dfv2 > 0.0 ) // sunrise occurs this hour
{
bsunrise = true; // sunup.bas 640
bsunrisetoday = true; // sunrise occurred today
}
if ( dfv0 > 0.0 && dfv2 < 0.0 ) // sunset occurs this hour
{
bsunset = true; // sunup.bas 660
bsunsettoday = true; // sunset occurred today
}
tempe = ( tempd - tempb ) / ( 2.0 * tempa );
if ( tempe > 1.0 || tempe < 0.0 ) // sunup.bas 670, 680
tempe = ( -tempd - tempb ) / ( 2.0 * tempa );
// set values of hour and minute of sunset or sunrise
// only if sunrise/set occurred this hour.
if ( bsunrise )
{
dfhourrise = math.floor( dfc0 + tempe + 1.0/120.0 );
dfminrise = math.floor(
( dfc0 + tempe + 1.0/120.0
- dfhourrise
)
* 60.0
);
}
if ( bsunset )
{
dfhourset = math.floor( dfc0 + tempe + 1.0/120.0 );
dfminset = math.floor(
( dfc0 + tempe + 1.0/120.0
- dfhourset
)
* 60.0
);
}
// change settings of variables for next loop
dfa0 = dfa2; // sunup.bas 250
dfd0 = dfd2; // sunup.bas 250
} // end of loop testing each hour for an event
// after having checked all hours, set flags if no rise or set
// bsunupallday and bsundownallday are initialized as false
if ( !bsunrisetoday && !bsunsettoday )
{
if ( dfv2 < 0.0 )
bsundownallday = true;
else
bsunupallday = true;
}
// load datesunrise with data
dfmtdatetime = new simpledateformat( "d m yyyy hh:mm z" );
if( bsunrisetoday )
{
datesunrise = dfmtdatetime.parse( iday
+ " " + imonth
+ " " + iyear
+ " " + (int)dfhourrise
+ ":" + (int)dfminrise
+ " gmt" );
}
// load datesunset with data
if( bsunsettoday )
{
datesunset = dfmtdatetime.parse( iday
+ " " + imonth
+ " " + iyear
+ " " + (int)dfhourset
+ ":" + (int)dfminset
+ " gmt" );
}
} // end of try
// catch errors
catch( parseexception e )
{
system.out.println( "\ncannot parse date" );
system.out.println( e );
system.exit( 1 );
} // end of catch
}
/******************************************************************************
* method: getsunrise()
*******************************************************************************
*
* gets the date and time of sunrise. if there is no sunrise, returns null.
*
* member of sunrisesunset class
*
* -------------------------------------------------------------------------- */
public date getsunrise()
{
if ( bsunrisetoday )
return( datesunrise );
else
return( null );
}
/******************************************************************************
* method: getsunset()
*******************************************************************************
*
* gets the date and time of sunset. if there is no sunset, returns null.
*
* member of sunrisesunset class
*
* -------------------------------------------------------------------------- */
public date getsunset()
{
if ( bsunsettoday )
return( datesunset );
else
return( null );
}
/******************************************************************************
* method: issunrise()
*******************************************************************************
*
* returns a boolean identifying if there was a sunrise.
*
* member of sunrisesunset class
*
* -------------------------------------------------------------------------- */
public boolean issunrise()
{
return( bsunrisetoday );
}
/******************************************************************************
* method: issunset()
*******************************************************************************
*
* returns a boolean identifying if there was a sunset.
*
* member of sunrisesunset class
*
* -------------------------------------------------------------------------- */
public boolean issunset()
{
return( bsunsettoday );
}
/******************************************************************************
* method: issunup()
*******************************************************************************
*
* returns a boolean identifying if the sun is up all day.
*
* member of sunrisesunset class
*
* -------------------------------------------------------------------------- */
public boolean issunup()
{
return( bsunupallday );
}
/******************************************************************************
* method: issundown()
*******************************************************************************
*
* returns a boolean identifying if the sun is down all day.
*
* member of sunrisesunset class
*
* -------------------------------------------------------------------------- */
public boolean issundown()
{
return( bsundownallday );
}
/******************************************************************************
* method: isdaytime()
*******************************************************************************
*
* returns a boolean identifying if it is daytime at the hour contained in
* the date object passed to sunrisesunset on construction.
*
* member of sunrisesunset class
*
* -------------------------------------------------------------------------- */
public boolean isdaytime()
{
// determine if it is daytime (at sunrise or later)
// or nighttime (at sunset or later) at the location of interest
// but expressed in the time zone requested.
if ( bsunrisetoday && bsunsettoday ) // sunrise and sunset
{
if ( datesunrise.before( datesunset ) ) // sunrise < sunset
{
if (
(
dateinput.after( datesunrise )
dateinput.equals( datesunrise )
)
&&
dateinput.before( datesunset )
)
bdaytime = true;
else
bdaytime = false;
}
else // sunrise comes after sunset (in opposite time zones)
{
if (
(
dateinput.after( datesunrise )
dateinput.equals( datesunrise )
)
|| // use or rather than and
dateinput.before( datesunset )
)
bdaytime = true;
else
bdaytime = false;
}
}
else if ( bsunupallday ) // sun is up all day
bdaytime = true;
else if ( bsundownallday ) // sun is down all day
bdaytime = false;
else if ( bsunrisetoday ) // sunrise but no sunset
{
if ( dateinput.before( datesunrise ) )
bdaytime = false;
else
bdaytime = true;
}
else if ( bsunsettoday ) // sunset but no sunrise
{
if ( dateinput.before( datesunset ) )
bdaytime = true;
else
bdaytime = false;
}
else bdaytime = false; // this should never execute
return( bdaytime );
}
} // end of class
/*-----------------------------------------------------------------------------
* end of class
*----------------------------------------------------------------------------*/