android 根據座標日期計算日出日落時間表

路燈監控:根據座標,時間段算出,日出日落作息16進製作息表

1、效果圖

2、代碼部分 

2.1、SunRiseSet 工具類

package com.lg.sun;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 算出日出日落時間
 * 
 * (1)先計算出從格林威治時間公元2000年1月1日到計算日天數days; 
 * (2)計算從格林威治時間公元2000年1月1日到計算日的世紀數t, 則t=(days+UTo/360)/36525; 
 * (3)計算太陽的平黃徑 : L=280.460+36000.770×t; 
 * (4)計算太陽的平近點角 :G=357.528+35999.050×t 
 * (5)計算太陽的黃道經度 :λ=L+1.915×sinG+0.020xsin(2G); 
 * (6)計算地球的傾角     ε=23.4393-0.0130×t; 
 * (7)計算太陽的偏差     δ=arcsin(sinε×sinλ); 
 * (8)計算格林威治時間的太陽時間角GHA: GHA=UTo-180-1.915×sinG-0.020×sin(2G)   +2.466×sin(2λ)-0.053×sin(4λ) 
 * (9)計算修正值e: e=arcos{[   sinh-sin(Glat)sin(δ)]/cos(Glat)cos(δ)}
 * (10)計算新的日出日落時間 :UT=UTo-(GHA+Long±e); 其中“+”表示計算日出時間,“-”表示計算日落時間; 
 * (11)比較UTo和UT之差的絕對值,如果大於0.1°即0.007小時,把UT作爲新的日出日落時間值,重新從第(2)步開始進行迭代計算,如果UTo和UT之差的絕對值小於0.007小時,則UT即爲所求的格林威治日出日落時間; 
 * (12)上面的計算以度爲單位,即180°=12小時,因此需要轉化爲以小時表示的時間,再加上所在的時區數Zone,即要計算地的日出日落時間爲 :T=UT/15+Zone 
 * 上面的計算日出日落時間方法適用於小於北緯60°和南緯60°之間的區域,如果計算位置爲西半球時,經度Long爲負數。
 */
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 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);

            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);


            return (int) (sunset / 15 + 8) + ":" + (int) (60 * (sunset / 15 + 8 - (int) (sunset / 15 + 8)));
        }
        return null;
    }


    /**
          * 將當前時間轉換爲16進制
          * @return
          */
    public static String getTimeTo16(String  time) {
        Date date = null;
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
//				date = formatter.parse("2020-03-26 16:03:55");
            date = formatter.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //Date格式
        Long  t =   date.getTime()/1000;
        String hexString = Long.toHexString(t);
        System.out.println("十六進制:"+hexString);

        return hexString;
    }


    //將指定時間轉換成 date 格式
    public static Date getTime(String time) {
        Date date = null;
//   	 SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd");           //日期
        try {
            date = formatter.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}


2.2、MainActivity

package com.lg.sun;

import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class MainActivity extends AppCompatActivity {

    private EditText edit_longitude, edit_latit, edit_date, date_start, date_end;
    private TextView tv;

    public Button btSave;

    public  String sunrise, sunset;

    public  String str1, str2;

    public  Double longitude, latit;

    public  String tvTime, SunriseSunsetDate;

    public String longitudeText, latitTextHint, datetime, dateEnd, dateStart;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//        test();
        init();
    }


    private void init() {
        btSave = findViewById(R.id.bt_save);
        edit_longitude = findViewById(R.id.longitude);
        edit_latit = findViewById(R.id.latit);
        edit_date = findViewById(R.id.date);
        date_start = findViewById(R.id.date_start);             //起始時間
        date_end = findViewById(R.id.date_end);                 //結束時間
        tv = findViewById(R.id.tv);
        findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String longit = edit_longitude.getText().toString();
                String latitText = edit_latit.getText().toString();

                String dateText = edit_date.getText().toString();
                String startTime = date_start.getText().toString();
                String endTime = date_end.getText().toString();

                //經度
                if (longit.isEmpty()) {              //如果無輸入,則讀取默認值
                    longitudeText = edit_longitude.getHint().toString();

                    Log.d("longitudeText --->", longitudeText);
                } else {
                    longitudeText = edit_longitude.getText().toString();
                }

                //緯度
                if (latitText.isEmpty()) {
                    latitTextHint = edit_latit.getHint().toString();

                    Log.d("latitTextHint====》", latitTextHint);
                } else {
                    latitTextHint = edit_latit.getText().toString();
                }

                if (!dateText.isEmpty()) {
                    datetime = edit_date.getText().toString();

                    Log.d("dateTime", datetime);
                } else {
                    datetime = edit_date.getHint().toString();
                    Log.d("dateTime = ", datetime);
                }

                //起始時間
                if (!startTime.isEmpty()) {               //起始時間
                    dateStart = date_start.getText().toString();

                    Log.d("dateStart", dateStart);
                } else {
                    dateStart = date_start.getHint().toString();
                    Log.d("dateStart = ", dateStart);
                }

                //結束時間
                if (!endTime.isEmpty()) {                 //結束時間
                    dateEnd = date_end.getText().toString();

                    Log.d("date_end", dateEnd);
                } else {
                    dateEnd = date_end.getHint().toString();
                    Log.d("date_end = ", dateEnd);
                }

                longitude = Double.parseDouble(longitudeText);       //經度

                latit = Double.parseDouble(latitTextHint);           //緯度

                //遍歷全年日期 賦值datetime ,得出 日出日落16進制時間表
                getDateToYear(dateStart, dateEnd, longitude, latit);

                tv.setText(tvTime);

                btSave.setVisibility(View.VISIBLE);
            }
        });

        btSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //寫入文件數據
                saveDate(SunriseSunsetDate);
            }
        });
    }


    /**
     * @param longitude   經度
     * @param latit        緯度
     * @param dateTime      日期
     */
    public  void earchDate(Double longitude, Double latit, String dateTime) {

        //1、輸入座標、日期,計算出日出日落時間
        str1 = SunRiseSet.getSunrise(new BigDecimal(longitude), new BigDecimal(latit), SunRiseSet.getTime(dateTime));
        str2 = SunRiseSet.getSunset(new BigDecimal(longitude), new BigDecimal(latit), SunRiseSet.getTime(dateTime));

        //2、獲取今天的日期  2020-03-26
        Date time = SunRiseSet.getTime(dateTime);
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");//Date指定格式:yyyy-MM-dd HH:mm:ss:SSS
        String format = simpleDateFormat1.format(time);

        //3、組成  2020-03-26 18:21:55
        String morning = format + " " + str1 + ":15";
        String evening = format + " " + str2 + ":25";

        Log.d("sunrise",morning);
        Log.d("sunset",evening);

        //4、將日出日落時間--->轉成16進制
        sunrise = SunRiseSet.getTimeTo16(morning);
        sunset = SunRiseSet.getTimeTo16(evening);

    }

    private  void getDateToYear(String start, String end, Double longitude, Double latit) {
        Calendar calendar1 = new GregorianCalendar();
        Calendar calendar2 = new GregorianCalendar();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date dayStart = df.parse(start); //按照yyyy-MM-dd格式轉換爲日期
            Date dayEnd = df.parse(end);
            calendar1.setTime(dayStart); //設置calendar的日期
            calendar2.setTime(dayEnd);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        for (; calendar1.compareTo(calendar2) <= 0; ) {   //calendar1在calendar2之前就循環

            String allDate = calendar1.get(Calendar.YEAR) + "-" + calendar1.get(Calendar.MONTH) + "-" + calendar1.get(Calendar.DATE);

            Log.d("時間", allDate);
            calendar1.add(Calendar.DAY_OF_YEAR, 1);  //加1天

            //算出日出日落時間
            earchDate(longitude, latit, allDate);
//
            Log.d("日出:", sunrise);
            Log.d("日落:", sunset);

            String  string = "日出:"+sunrise+" 日落:"+sunset;

            tvTime += string;
//
            SunriseSunsetDate ="日出:"+sunrise+" 日落:"+sunset;

        }
    }

    /**
     * @param str  存儲數據
     */
    public  void saveDate(String str) {

        String filePath = null;

        boolean hasSDCard = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);

        if (hasSDCard) {
            filePath = Environment.getExternalStorageDirectory().toString() + File.separator + "datetime.txt";
        } else {
            filePath = Environment.getDownloadCacheDirectory().toString() + File.separator + "datetime.txt";
        }
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                File dir = new File(file.getParent());
                dir.mkdirs();
                file.createNewFile();
            }
            BufferedWriter fout = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream(file,true)));
            fout.write(str + "\n");
            fout.close();

        } catch (Exception e) {
            e.printStackTrace();

        }

    }

}

2.3、清單文件及頁面

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.lg.sun">
    
    <uses-permission android:name="android.permission.INTERNET"/>

    <!--寫入權限-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
        tools:ignore="ProtectedPermissions" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/longitude"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="118.7720775600" />

    <EditText
        android:id="@+id/latit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="31.9788128700" />

    <EditText
        android:id="@+id/date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="2020-03-26"
        android:visibility="gone" />


    <EditText
        android:id="@+id/date_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="2020-01-01" />


    <EditText
        android:id="@+id/date_end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="2020-12-31" />

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">


        <Button
            android:id="@+id/bt"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:hint="查詢" />

        <Button
            android:visibility="invisible"
            android:id="@+id/bt_save"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:hint="保存" />

    </LinearLayout>

    <ScrollView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=" "
            android:textSize="16dp" />


    </ScrollView>


</LinearLayout>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章