简体   繁体   中英

How convert 1 year to seconds with Joda-Time?

There is Years class in Joda-Time api,but it does not have any methods for getting seconds or milliseconds (or any methods about converting it to Duration ). Also there is a DateTimeConstants with useful constants, but again without any SECONDS_PER_YEAR constant.

So how convert 1 year to seconds with joda time?

There isn't a constant for the number of seconds in one year because you must first decide a constant for number of days in one year. Using TimeUnit (Java 5+) you could use

System.out.println(TimeUnit.SECONDS.convert(365, TimeUnit.DAYS));
System.out.println(TimeUnit.SECONDS.convert(365, TimeUnit.DAYS)
        + TimeUnit.SECONDS.convert(6, TimeUnit.HOURS));
System.out.println(TimeUnit.SECONDS.convert(366, TimeUnit.DAYS));

to get the number of seconds for 365 days (a typical year), 365.25 days (a "spherical" year) and 366 days (a leap year ). I get

31536000
31557600
31622400

That could be generalized as an enum like

public enum YEAR {
    TYPICAL(TimeUnit.SECONDS.convert(365, TimeUnit.DAYS)), //
    SPHERICAL(TimeUnit.SECONDS.convert(365, TimeUnit.DAYS) //
        + TimeUnit.SECONDS.convert(6, TimeUnit.HOURS)), //
    LEAP(TimeUnit.SECONDS.convert(366, TimeUnit.DAYS));
    YEAR(long seconds) {
        this.seconds = seconds;
    }

    long seconds;

    public long getSeconds() {
        return seconds;
    }

    public static YEAR forYear(int year) {
        if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
            return LEAP;
        }
        return TYPICAL;
    }
}

And to test it (and reproduce the same output)

public static void main(String[] args) {
    int year = 2016;
    System.out.println(YEAR.forYear(year).getSeconds());
    System.out.println(YEAR.SPHERICAL.getSeconds());
    System.out.println(YEAR.forYear(year + 1).getSeconds());
}

However, as pointed out in the comments, this doesn't account for leap seconds .

tl;dr

java.util.concurrent.TimeUnit.DAYS.toSeconds(   // Assuming generic 24-hour days.
    Year.of( 2018 ).length()                    // Get number of days in year, either 365 or 366 (leap year).
)                                               // Return a `long`, a count of seconds in year assuming 24-hour days. 

31536000

That result is approximate, assuming generic 24-hour days. For a more accurate number, see Exact number of seconds section below.

java.time

The modern approach uses the java.time classes. Note that java.time uses a resolution of nanoseconds , much finer than Joda-Time's milliseconds .

The Joda-Time project is now in maintenance mode , with the team advising migration to the java.time classes.

Generic number of seconds

If you want a general count of seconds assuming generic 24-hour days, use TimeUnit enum, Year class, and a little math. This approach ignores leap second.

long secondsPerGenericDay = TimeUnit.DAYS.toSeconds( 1 ) ;  // Assuming 24-hour days.
long days = Year.of( 2018 ).length() ;  // Either 365 or 366 depending on leap year.
long seconds = ( days * secondsPerGenericDay ) ;

…or…

long secondsInYear = TimeUnit.DAYS.toSeconds( Year.of( 2018 ).length() ) ;

See this code run live at IdeOne.com .

seconds: 31536000 = secondsInYear: 31536000

See also correct Answer by Elliott Frisch .

Exact number of seconds

If you want exact number of seconds in a year, that can vary by time zone. Anomalies such as Daylight Saving Time (DST) or other changes to a zone's definition made by politicians mean that days can vary in length. They are not always exactly 24 hours in length.

The approach below does ignore leap seconds , when using a common implementation of Java. Leap seconds are unpredictable, so you must look to a historical record if you want to add them into your calculation. In advance, they are scheduled out only a few months.

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone.

A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec .

Specify a proper time zone name in the format of continent/region , such as America/Montreal , Africa/Casablanca , or Pacific/Auckland . Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );

Year

The Year class can assist.

Year y = Year.now( z ) ;

LocalDate start = y.atDay( 1 ) ;
LocalDate stop = start.plusYears( 1 ) ;

First moment of the day

We need specific moments to calculate seconds. So need the first moment of each date.

Let java.time determine the first moment. Anomalies such as DST mean the day may start at some time other than 00:00.

ZonedDateTime zdtStart = start.atStartOfDay( z ) ;
ZonedDateTime zdtStop = stop.atStartOfDay( z ) ;

Elapsed time

We can represent a span of time unattached to the timeline with a resolution of seconds plus fractional second using the Duration class.

Duration d = Duration.between( zdtStart , zdtStop ) ;

Interrogate for the number of whole seconds.

long seconds = d.getSeconds() ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat .

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes.

To learn more, see the Oracle Tutorial . And search Stack Overflow for many examples and explanations. Specification is JSR 310 .

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more .

What is leap? :) If you ask about days in year it should be 365. Just standard minute, hour and days. It should be 60*60*24*365 seconds in year, but is there a constant for that?

No there isn't.

And the reason is that the number of days (and hence seconds) in a year is not constant.

Really.

It is either 365 or 366 ... depending on which year you are talking about.

So why didn't they define two constants for the 365 and 366 day cases? I guess because they deemed it would be harmful. (For instance, it could lead to people writing applications that assume that every year has 365 days ... and get their interval calculations wrong.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM