Convert a Julian Date to an Instant

前端 未结 4 1627
再見小時候
再見小時候 2021-01-05 14:58

I\'m running into a situation where I would like to convert from a Julian date to an java.time.Instant (if that makes sense), or some Java time that can be more easily under

4条回答
  •  孤独总比滥情好
    2021-01-05 15:10

    I am going to assume that you have a numeric timestamp that is a kind of modified Julian Day Number, i.e. a continuous count of days since a defined epoch.

    For example, the definition of a "Modified Julian Day Number" is a continuous count of days since midnight on Nov 17, 1858. I believe what you are asking is:

    How do I convert a continuous count of days in England since the Gregorian Calendar was officially adopted to an Instant?

    I'm not certain where the Gregorian Epoch officially began after the New Style Calendar act. I will assume that it is January 1, 1752, i.e. the number 95906.276 is a continuous count of days since then.

    METHOD1: Here is an algorithm for processing a day number to an integer array representation in year, month(1-12), day(1-31), hours(0-23), min(0-59), sec(0-59), millis:

        private static final int                   YEAR = 0;
        private static final int                  MONTH = 1;
        private static final int                    DAY = 2;
        private static final int                  HOURS = 3;
        private static final int                MINUTES = 4;
        private static final int                SECONDS = 5;
        private static final int                 MILLIS = 6;
    
        public static int[] toTimeStampArray(double yourEpochDayNumber) {
    
            int ymd_hms[] = { -1, -1, -1, -1, -1, -1, -1 };
            int a, b, c, d, e, z;
    
            // convert from your epoch (1/1/1752) to Julian Day Number
            double jd = yourEpochDayNumber + 2360965.5 + 0.5;
            double f, x;
    
            z = (int) Math.floor(jd);
            f = jd - z;
    
            if (z >= 2299161) {
                int alpha = (int) Math.floor((z - 1867216.25) / 36524.25);
                a = z + 1 + alpha - (int) Math.floor(alpha / 4);
            } else {
                a = z;
            }
    
            b = a + 1524;
            c = (int) Math.floor((b - 122.1) / 365.25);
            d = (int) Math.floor(365.25 * c);
            e = (int) Math.floor((b - d) / 30.6001);
    
            ymd_hms[DAY] = b - d - (int) Math.floor(30.6001 * e);
            ymd_hms[MONTH] = (e < 14)
                    ? (e - 1)
                    : (e - 13);
            ymd_hms[YEAR] = (ymd_hms[MONTH] > 2)
                    ? (c - 4716)
                    : (c - 4715);
    
            for (int i = HOURS; i <= MILLIS; i++) {
                switch(i) {
                    case HOURS:
                        f = f * 24.0;
                        break;
                    case MINUTES: case SECONDS:
                        f = f * 60.0;
                        break;
                    case MILLIS:
                        f = f * 1000.0;
                        break;  
                }
                x = Math.floor(f);
                ymd_hms[i] = (int) x;
                f = f - x;
            }   
            return ymd_hms;
        }
    

    Algorithm is adapted from Meeus J., Astronomical Algorithms, 2nd Ed.

    From these data, you can create a LocalDateTime instance. You can combine that with a ZoneId instance to create a ZonedDateTime and get an Instant.

    METHOD 2. If your day number is already reckoned in GMT/UTC and does not require any offsets for time zone or daylight savings, then you can convert directly from a day number (in your epoch) to an Instant as follows:

    public Instant dayNumberToInstant(double dayNumber) {
        long millisFromPosixEpoch;
    
        final double POSIX_EPOCH_AS_DAYNUM = 79622.0
    
        millisFromPosixEpoch = (long) ((dayNumber - POSIX_EPOCH_AS_DAYNUM) *
            (86400.0 * 1000.0));
        return Instant.ofEpochMillis(millisFromPosixEpoch);
    }
    

提交回复
热议问题