001package jmri.util;
002
003import java.util.Calendar;
004import java.util.GregorianCalendar;
005
006/**
007 * Common utility methods for working with Calendar and Date objects.
008 *
009 * @author Paul Bender Copyright 2014
010 */
011public class DateUtil {
012
013    // class only supplies static methods
014    private DateUtil(){}
015
016    /**
017     * Return a GregorianCalendar representation of the given julian date.
018     * For reference, see: http://aa.usno.navy.mil/faq/docs/JD_Formula.php
019     * @param julianDay number of days since January 1,4713BC.
020     * @return {@link java.util.GregorianCalendar} representation of julianDay
021     */
022    public static GregorianCalendar calFromJulianDate(long julianDay) {
023        long l = julianDay + 68569;
024        long n = 4 * l / 146097;
025        l -= (146097 * n + 3) / 4;
026        long year = 4000 * (l + 1) / 1461001;
027        l = l - 1461 * year / 4 + 31;
028        long month = 80 * l / 2447;
029        long day = l - 2447 * (month) / 80 - 31;
030        l = month / 11;
031        month = month + 2 - 12 * l;
032        year = 100 * (n - 49) + year + l;
033        return  new GregorianCalendar((int) year, (int) month, (int) day, 0, 0);
034    }
035
036    /**
037     * Return a julian date representation of the given GregorianCalendar date.
038     * for reference, see: http://aa.usno.navy.mil/faq/docs/JD_Formula.php
039     * @param cal the GregorianCalendar to convert.
040     * @return julianDate representation of the date represented by cal.
041     */
042    public static long julianDayFromCalendar(java.util.GregorianCalendar cal) {
043        int i = cal.get(Calendar.YEAR);
044        int j = cal.get(Calendar.MONTH) + 1; // GregorianCalendar starts month
045        // at 0.  Calculation requres month
046        // starting at 1.
047
048        int k = cal.get(Calendar.DAY_OF_MONTH);
049
050        return k - 32075 + 1461 * (i + 4800 + (j - 14) / 12) / 4 +
051            367 * (j - 2 - (j - 14) / 12 * 12) / 12 - 3 * ((i + 4900 + (j - 14) / 12) / 100) / 4;
052    }
053
054    /**
055     * For a given number of seconds, format to a more human readable form.
056     * Negative durations are prepended by the minus symbol.
057     * For durations less than 24hrs, the day integer is omitted.
058     * @param seconds the number of seconds
059     * @return string representation of duration in D hh:mm:ss form.
060     */
061    public static String userDurationFromSeconds(int seconds) {
062        String minus = ( seconds < 0 ? "- " : "" );
063        var duration = java.time.Duration.ofSeconds(Math.abs(seconds));
064        long days = duration.toDays();
065        long hours = duration.minusDays(days).toHours();
066        long mins = duration.minusDays(days).minusHours(hours).toMinutes();
067        long secs = duration.minusDays(days).minusHours(hours).minusMinutes(mins).toSeconds();
068        if ( days == 0 ) {
069            return minus + String.format("%02d:%02d:%02d", hours, mins, secs);
070        }
071        else {
072            return minus + String.format("%d %02d:%02d:%02d", days, hours, mins, secs);
073        }
074    }
075
076}