获取日出和日落时间

获取日出和日落时间

我试图使用这个类从日期中获取日出和日落时间,但我有一个时区作为 Timezone 对象。此类构造函数需要将时区作为 double 值。

如何将我的时区转换为 double 时区?

/******************************************************************************
*   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,double dfLonIn,Date dateInputIn,double dfTimeZoneIn)
    {
        // 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
*----------------------------------------------------------------------------*/

最佳答案

我知道你从 here 得到了源代码。看起来这是一个非常古老的来源。
使用可用的最新版本 here

看起来你可以通过以下代码实现这里。

Location location = new Location("39.9522222", "-75.1641667");
// Pass the time zone display here in the second parameter.
SunriseSunsetCalculator calculator = new SunriseSunsetCalculator(location, "America/New_York");

关于java - 获取日出和日落时间,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15241392/

10-08 20:37