简体   繁体   中英

Use different date as UNIX epoch time in Java?

I know that the standard UNIX epoch time is 1/1/70 and I can use this variable to convert current time to UNIX time:

int time = (int) ((System.currentTimeMillis())/1000);

(Note: I know it's normally stored as a 64-bit long but I need it to be 32 bit, hence the cast to int).

My question is - are there any built-in methods in Java where you can pass in a different date as the "epoch date." What I am trying to get is a timestamp in # of seconds since a particular date. Ie I would like to define January 1, 2015 as MY epoch. And then each future date would be # of seconds since 1/1/2015.

If there's no Java library that provides that capability, any ideas on how to do this? Thanks, Tim

There is no library needed, you just have to use maths.

static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
static final long EPOCH = new Date(2015 - 1900, Calendar.JANUARY, 1).getTime(); // 2015/1/1 in GMT

public static int secondSinceEpoch() {
    return (int) ((System.currentTimeMillis() - EPOCH) / 1000);
}

public static String epochToString(int secsSince2015) {
    return SDF.format(new Date(secsSince2015 * 1000 + EPOCH));
}

public static void main(String... ignored) {
    System.out.println(new Date(EPOCH));
    System.out.println("Epoch is " + epochToString(0));
    System.out.println("Today is " + secondSinceEpoch() + " secs");
    System.out.println("Today is " + secondSinceEpoch() / 86400 + " days");
}

prints

Thu Jan 01 00:00:00 GMT 2015
Epoch is 2015/01/01 00:00:00
Today is -15732850 secs
Today is -182 days

You'd probably have to roll your own time and date methods, which would basically repackage the standard ones while subtracting the correct number of seconds to the epoch to arrive at your new epoch.

So, maybe something like

public class MyEpoch {
    public static final Long MY_EPOCH = //number of seconds betweer 1/1/70 and 1/1/2015
    private Date unixEpochDate;
    //etc
    public Long getMyEpoch() {
        return unixEpochDate.getTime() - MY_EPOCH;
    }
}

tl;dr

long totalSeconds = Duration.between ( OffsetDateTime.of ( 2015 , 1 , 1 , 0 , 0 , 0 , 0 , ZoneOffset.UTC ) , OffsetDateTime.now ( ZoneOffset.UTC ) ).getSeconds ();

Elapsed time

Forget about the epoch reference date . What you want is simply elapsed time.

java.time

The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date , .Calendar , & java.text.SimpleDateFormat . The Joda-Time team also advises migration to java.time.

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

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP .

Time zone

Your question fails to address the crucial issue of time zone.

Since you mentioned Unix-style time, I will assume you intended UTC time zone. The Instant class represents a moment on the timeline in UTC with a resolution up to nanosecond. For more flexibility including formatting, use an OffsetDateTime with an assigned offset of UTC instead.

Duration

The OffsetDateTime class represents a date and time-of-day with an assigned offset-from-UTC. We can specify the constant ZoneOffset.UTC as the offset value.

The Duration class represents a span of time as a total number of seconds plus a fractional second in nanoseconds. We can get a Duration object from our pair of OffsetDateTime objects.

Calling Duration::getSeconds gets the total number of seconds in the duration. But note that we may be losing data as any fractional second will naturally be omitted from the resulting number.

OffsetDateTime start = OffsetDateTime.of ( 2015 , 1 , 1 , 0 , 0 , 0 , 0 , ZoneOffset.UTC );
OffsetDateTime now = OffsetDateTime.now ( ZoneOffset.UTC );

Duration duration = Duration.between ( start , now );
long totalSeconds = duration.getSeconds ();

Dump to console.

System.out.println ( "start: " + start + " | now: " + now + " | duration: " + duration + " | totalSeconds: " + totalSeconds );

start: 2015-01-01T00:00Z | now: 2016-07-24T04:15:57.345Z | duration: PT13684H15M57.345S | totalSeconds: 49263357

Going the other direction, calculating a date-time from your starting point with a number of seconds, is easy. Just call plusSeconds .

Rather than dirty your code with “magic” numbers and math calculations to get a number of seconds, use the TimeUnit class.

OffsetDateTime start = OffsetDateTime.of ( 2015 , 1 , 1 , 0 , 0 , 0 , 0 , ZoneOffset.UTC );
long seconds = TimeUnit.HOURS.toSeconds ( 7 );  // Let `TimeUnit` class do the math of calculating seconds.
OffsetDateTime stop = start.plusSeconds ( seconds );

2015-01-01T07:00Z

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