有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaScriptJava从儒略日数到公历日期和时间的计算

最近我看到了一个漂亮的javascript库,它计算特定日期、纬度和经度的太阳时间。因为我想在我的一些安卓开发中使用它,所以我正在将该库重写为java。 由于使用朱利安日而不是公历日期来计算时间要容易得多,所以我必须将日期转换为朱利安日期。但为了给出某个事件发生的时间,我必须将儒略日数转换为公历日期和时间

在javascript中,从朱利安日数到朱利安日数的转换非常容易。javascript的计算如下所示:

var dayMS = 1000 * 60 * 60 * 24;
var J1970 = 2440588;
var J2000 = 2451545;

function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; }
function fromJulian(j)  { return new Date((j + 0.5 - J1970) * dayMs); }

但是从朱利安日的数字转换过来给我带来了很多麻烦。我的上述java javascript版本是:

double dayMs = 1000 * 60 * 60 * 24;
double J1970 = 2440588;
double J2000 = 245154;

public double toJulian(LocalDateTime date) {
        ZonedDateTime zdt = date.atZone(ZoneId.of("Europe/Vienna"));
        double result = zdt.toInstant().toEpochMilli(); //milliseconds since epoch
        result = result / dayMs - 0.5 + J1970;

        return result;
    }

public String fromJulian(double jdn) {

        System.out.println("fromJulian.jdn: " + jdn);

        int jalpha,ja,jb,jc,jd,je,year,month,day;
        double  julian = jdn,
                decimal= jdn % 1;
        ja = (int) julian;
        if (ja>= JGREG) {
            jalpha = (int) (((ja - 1867216) - 0.25) / 36524.25);
            ja = ja + 1 + jalpha - jalpha / 4;
        }

        jb = ja + 1524;
        jc = (int) (6680.0 + ((jb - 2439870) - 122.1) / 365.25);
        jd = 365 * jc + jc / 4;
        je = (int) ((jb - jd) / 30.6001);
        day = jb - jd - (int) (30.6001 * je);
        month = je - 1;
        if (month > 12) month = month - 12;
        year = jc - 4715;
        if (month > 2) year--;
        if (year <= 0) year--;

        double dhour = decimal * 24;
        int hour = (int) Math.round(dhour);

        decimal = dhour % 1;

        double dminute = decimal * 60;
        int minute = (int) Math.round(dminute);

        decimal = dminute % 1;

        double dsecond = decimal * 60;
        int second = (int) Math.round(dsecond);

        LocalDateTime ldt = LocalDateTime.of(
            year,
            month,
            day,
            hour,
            minute,
            second
        );
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
        ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.of("UTC"));

        return dtf.format(zdt);
    }

javascript和java中的方法toJulian给了我完全相同的值,但是在julian的方法中,我不知怎么得到了一个日期,但是一个完全错误的日期


示例

日期=“2020年12月26日00:00:00”

Javascript:将日期插入函数toJulian,并将值(2459209.4583333335)重新插入函数fromJulian返回26 December 00:00:00

Java:将日期插入函数toJulian,并将值(2459209.4583333335)重新插入函数fromJulian返回25 December 11:00:00


两天以来,我尝试了用朱利安日数来计算格里高利日的不同方法,但从未达到预期的效果。我已经将整个java库上传到github(https://github.com/stnieder/SunCalc_Java)。我希望有人能帮我解决这个问题


共 (1) 个答案

  1. # 1 楼答案

    编辑:Java大致支持Julian day number。它能正确计算天数。它并不像朱利安日定义的那样在中午开始新的一天,也不支持一天中的一小部分时间。我们仍然可以利用这些支持,自己进行适当的调整

    据我所知,以下方法前后进行了一致的转换,并与您在JavaScript中从toJulian()获得的朱利安日数一致

    private static final double dayMs = Duration.ofDays(1).toMillis();
    
    public static double toJulian(LocalDateTime date) {
        LocalTime timeOfDay = date.toLocalTime();
        double result = date.getLong(JulianFields.JULIAN_DAY);
        result += timeOfDay.get(ChronoField.MILLI_OF_DAY) / dayMs - 0.5;
    
        return result;
    }
    
    public static LocalDateTime fromJulian(double jdn) {
        LocalDate date = LocalDate.EPOCH.with(JulianFields.JULIAN_DAY, (long) jdn);
        LocalDateTime result = date.atStartOfDay()
                .plusHours(12)
                .plus((long) (jdn % 1 * dayMs), ChronoUnit.MILLIS);
        
        return result;
    }
    

    尝试一下:

        LocalDateTime dateTime = LocalDateTime.of(2020, Month.DECEMBER, 26, 0, 0);
        double jdn = toJulian(dateTime);
        System.out.println(jdn);
        
        LocalDateTime convertedBack = fromJulian(jdn);
        System.out.println(convertedBack);
        System.out.println("Does it differ? " + Duration.between(dateTime, convertedBack));
    

    输出:

    2459209.5
    2020-12-26T00:00
    Does it differ? PT0S
    

    最后一行包含PT0S,时间段为0秒,因此结果与起点没有差异

    文档链接:^{}