zoukankan      html  css  js  c++  java
  • 判断任意时刻、位置是白昼?黑夜?

    问题描述:给定经纬度(lon,lat),计算某时刻(utc时间戳)是白天还是黑夜?

    package common.utils;
    
    import java.text.SimpleDateFormat;
    import java.util.TimeZone;
    
    /**
     * @description:①给定任意utc,计算该utc对应的白昼时长。调用函数:getDayTimeLength(int utc);
     * ②给定经纬度(lon,lat),计算某时刻(utc时间戳)是白天还是黑夜?
     * @author: fangchangtan
     * @create: 2019-01-14 15:10
     */
    public class DayNightUtil {
        private static SimpleDateFormat dateFormat = new SimpleDateFormat("D");
    
        /*
        角度转换为弧度的公式
         */
        private static double toRadians(double angel) {
            return Math.PI * angel / 180;
        }
    
        //1.计算utc对应的是一年中的第几天;计算num_days
        private static int getNdayInYear(int utc) {
            int year = Integer.valueOf(dateFormat.format(utc * 1000D));
            return year;
        }
    
        //2.计算b
        private static double getB(int num_days) {
            return 2 * Math.PI * (num_days - 1) / 365;
        }
    
        //3.计算solar_declination
        private static double getSolar_Declination(int utc) {
            int ndayInYear = getNdayInYear(utc);
            double b = getB(ndayInYear);
            double solar_declination = 0.006918 - 0.399912 * Math.cos(b)
                    + 0.070257 * Math.sin(b)
                    - 0.006758 * Math.cos(2 * b)
                    + 0.000907 * Math.sin(2 * b)
                    - 0.002697 * Math.cos(3 * b)
                    + 0.00148 * Math.sin(3 * b);
            return solar_declination;
        }
    
        /*
        4.计算t:昼长计算公式
        单位是小时
         */
        public static double getDayTimeLength(int utc, double currentLat) {
            double solar_declination = getSolar_Declination(utc);
            double dayLong = 0;
            dayLong = 24 - (2 / 15d) * Math.acos(Math.tan(toRadians(currentLat)) * Math.tan(solar_declination)) * (180 / Math.PI);
            if (Double.isNaN(dayLong) || Double.isInfinite(dayLong)) {
            //判断是不是极昼极夜
                if (Math.sin(toRadians(currentLat)) * Math.sin(solar_declination) > 0) {//是极昼现象
                    return 24;
                } else {//是极夜现象
                    return 0;
                }
            }
            return dayLong;
        }
    
    
        /*
        获取各个时区中的正午时间差值:单位s秒
        例如121度,是+240s
         */
        private static int getMidDayInTimeZone(double lon) {
            double value = lon % 15;
            int midday = (int) ((Math.abs(value) > 7.5 ? 15 - Math.abs(value) : Math.abs(value)) * Math.signum(value) * 4 * 60);
            return midday;
        }
    
        /**
         * 根据经度获取时区;例如121:+8;-121:-8;
         *
         * @param currentLon
         * @return
         */
        public static String caculateTimeZone(double currentLon) {
            int timeZone;
            int shangValue = (int) (currentLon / 15);
            double yushuValue = Math.abs(currentLon % 15);
            if (yushuValue <= 7.5) {
                timeZone = shangValue;
            } else {
                timeZone = shangValue + (currentLon > 0 ? 1 : -1);
            }
            return timeZone >= 0 ? "+" + Math.abs(timeZone) : "-" + Math.abs(timeZone);
        }
    
        private static SimpleDateFormat dateFormatYMD = new SimpleDateFormat("yyyy-MM-dd");
        private static SimpleDateFormat dateFormatHms = new SimpleDateFormat("HH:mm:ss");
    
        /**
         * func:判断白天,还是黑夜
         * isDayTime ? 1 : 2其中1:白天;2:是黑夜
         * @param utc
         * @param currentLon
         * @param currentLat
         * @return
         */
        public static int judegeDayOrNight(int utc, double currentLon, double currentLat) {
            //获得白昼时长
            double dayTimeLength = getDayTimeLength(utc, currentLat);
            System.out.println("dayTimeLength: " + dayTimeLength);
            //获得与中午12:00点的时间差。单位是s
            int middayOffset = getMidDayInTimeZone(currentLon);
            //获得时区编号
            String sTimeZone = caculateTimeZone(currentLon);
            dateFormatHms.setTimeZone(TimeZone.getTimeZone("GMT" + sTimeZone));
            String HHmmss = dateFormatHms.format(utc * 1000L);
            String[] split = HHmmss.split(":");
            double hour = 0;
            if (split.length == 3) {
                hour = Integer.valueOf(split[0]) + Integer.valueOf(split[1]) / 60 + Integer.valueOf(split[2]) / 3600;
            }
            //如果时间差值小于昼长的一半(t/2),则当前时刻为白昼,否则为黑夜
            boolean isDayTime;
            if ((12 + middayOffset / 3600) - dayTimeLength / 2 < hour && hour <= (12 + middayOffset / 3600) + dayTimeLength / 2) {
                isDayTime = true;
            } else {
                isDayTime = false;
            }
            return isDayTime ? 1 : 2;
        }
    
    
        /**
         * 主函数main
         * @param args
         */
        public static void main(String[] args) {
            for (int i = 0; i < 10; i++) {
    //            double nday = getDayTimeLength(1484611200, 10 * i);
    //            System.out.println("i:" + i + "; ndayLength:" + nday);
                int iDayTime = judegeDayOrNight(1484611200, 116, 10 * i);
                System.out.println(iDayTime);
            }
    
        }
    }
  • 相关阅读:
    中缀表达式std
    后缀表达式
    取石头游戏
    LeetCode404Sum of Left Leaves左叶子之和
    LeetCode387First Unique Character in a String字符串中第一个唯一字符
    简单排列习题2.5 的 2
    周期串Uva455 P37 3-4
    【递归】分形
    【递归】普通递归关系(矩阵快速幂)
    P3486 [POI2009]KON-Ticket Inspector
  • 原文地址:https://www.cnblogs.com/yangyuxiaozi/p/3774718.html
Copyright © 2011-2022 走看看