javadatedatetime-formatdate-conversionjulian-date

How to convert a D M Y HH:MM:SS string in Java to Julian Date?


I have some strings in Java that come in the format: Day Month Year Hour:Minute:Second

7 Jan 2010 23:00:00.000
4 Feb 2010 17:40:00.000

What is the easiest way to parse this string and convert the values to their resulting Julian Dates? I am reading in these strings from Excel so they are not objects with any sort of conversion/formatting utilities (just raw strings). Is there an easy library or function to call to convert these, or would I have to manually write a parser? Thanks


Solution

  • java.time

    Sure, Java has got a parser for date and time built-in, the DateTimeFormatter class (named so because it can also format date and time back to strings). And a number of classes that can utilize it for producing objects of themselves. In your case you need the LocalDateTime class. A LocalDateTime is a date and time of day without time zone or offset from UTC, so appropriate for holding the data from your string.

    This formatter s good for your string:

    private static final DateTimeFormatter FORMATTER
            = DateTimeFormatter.ofPattern("d MMM uuuu HH:mm:ss.SSS", Locale.ENGLISH);
    

    Edit: You wrote in a comment:

    Plugging in Jan 7 2010 hour 23 into this calculator: aavso.org/jd-calculator gives back 2455204.45833. Would this be the exact Julian Date? I believe your solution was giving the Day instead of Date decimal value

    Yes, that’s exactly true. The modified code to get the julian date including the fraction is:

        String source = "7 Jan 2010 23:00:00.000";
        
        LocalDateTime ldt = LocalDateTime.parse(source, FORMATTER);
        // Subtract half a day to compensate for the
        // fact that the Julian day begins at noon
        LocalDateTime dateToUseForJulianDay = ldt.minusHours(12);
        long julianDayNumber = dateToUseForJulianDay.getLong(JulianFields.JULIAN_DAY);
        double juianDateFraction = (double) dateToUseForJulianDay.getLong(ChronoField.NANO_OF_DAY)
                / (double) Duration.ofDays(1).toNanos();
        double julianDate = julianDayNumber + juianDateFraction;
        
        System.out.println("Julian date: " + julianDate);
    

    And the output is in this example:

    Julian date: 2455204.4583333335

    It agrees very nicely with thee result you quote from the online calculator.

    The Julian day number is the day number since January 1, 4713 BC. The Julian day starts at noon, which Java does not take into account, so as a hack I have subtracted 12 hours to compensate and get the correct day for all times of day. Since the getLong() method only gets the Julian day number as a whole number, I need to find the fraction separately. It’s a matter of dividing the nanosecond of the day by the total number of nanoseconds in a day. From the original date and time we would have needed the number of nanos since 12 noon; but since I have already subtracted 12 hours, the nanosecond of the day, since 0:00 midnight, is the number we need.

    Further link: Julian day on Wikipedia