300

Date.getTime() returns milliseconds since Jan 1, 1970. Unixtime is seconds since Jan 1, 1970. I don't usually code in java, but I'm working on some bug fixes. I have:

Date now = new Date();      
Long longTime = new Long(now.getTime()/1000);
return longTime.intValue();

Is there a better way to get unixtime in java?

Per Lundberg
  • 3,837
  • 1
  • 36
  • 46
Gary Richardson
  • 16,081
  • 10
  • 53
  • 48
  • 30
    Since you're cast it to an int, you've introduced the year 2038 problem (the equivalent of Y2K for Unix). That's when Unix epoch hits 2 billion and rolls over to negative. The fix is to move to 64-bit Unix. The Java equivalent is to leave it as a long. – John M Apr 30 '09 at 03:16
  • 1
    Yes, I am aware of that. The code this is interfacing with is expecting a 32bit int for unixtime. – Gary Richardson Apr 30 '09 at 04:37
  • 172
    2038 is coming soon. – Pacerier Jan 13 '12 at 10:17
  • Is there a proper name or standard for currentTimeMillis? I tend to refer to it in my documentation as the millisecond version of UNIX time. – Tom Feb 05 '13 at 21:30
  • I believe a formal version which everyone would aknowledge is: current time in milliseconds since the UNIX epoch (Jan 1, 1970). – Sandman Aug 26 '13 at 21:00
  • I tend to use epoch seconds and epoch milliseconds. That's clear enough. What other epoch could there possibly be? – jettero Sep 15 '13 at 20:11
  • @jettero `What other epoch could there be?` There are at least about [20 other epochs](http://en.wikipedia.org/wiki/Epoch_(reference_date)). Multiply that by the fact that some libraries count seconds (Unix), some milliseconds (java.util.Date, Joda-Time DateTime), some microseconds, and some nanoseconds (java.time). And factor in 32-bit versus 64-bit numbers. That adds up to a mess. Best to avoid count-from-epoch. Instead serialize to [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601) format such as: `2014-07-11T04:22:46Z`. – Basil Bourque Jul 11 '14 at 20:27

3 Answers3

532

Avoid the Date object creation w/ System.currentTimeMillis(). A divide by 1000 gets you to Unix epoch.

As mentioned in a comment, you typically want a primitive long (lower-case-l long) not a boxed object long (capital-L Long) for the unixTime variable's type.

long unixTime = System.currentTimeMillis() / 1000L;
John M
  • 13,053
  • 3
  • 27
  • 26
  • 3
    Also consider using primitive long instead of autoboxing to Long, unless you want to handle the number as an Object (like put it into a Collection), again avoids unnecessary object creation – brabster Apr 08 '09 at 22:05
  • 9
    The Java 32-bit int matches 32-bit platforms (and the year 2038 problem). 64-bit platforms use a larger time_t data type. Java dodged that bullet by using a long as the return for System.currentTimeMillis(). If you convert to int, you're re-introducing the year 2038 problem. See http://en.wikipedia.org/wiki/Year_2038_problem#Solutions – John M Feb 27 '12 at 16:26
  • What happens if this division returns a fractional number? is it automatically rounded? – Ali Oct 18 '13 at 17:36
  • @ClickUpvote The numerator and denominator are both longs, so it's integer division. – slypete Oct 25 '13 at 21:59
  • so.. if you did `int foo = 11 / 7`, the answer will always be 1? – Ali Oct 26 '13 at 06:06
  • 1
    I think you are mistaken on one point: There is no difference between a lower case "L" and an upper case one when using them in numeric literals like this. http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.1 – matt forsythe Jul 17 '14 at 20:21
  • 5
    The capitalization discussion (clarified above) was about the data type. Primitive "long" vs "java.lang.Long" class instance. You're talking about the suffix letter on the long literal, which I agree can be upper or lower case. Though lower case "l" looks a heck of a lot like the digit "1" so it's much more readable to use capital "L". – John M Jul 18 '14 at 15:38
  • The problem with this is that it doesn't account for other timezones. For instance, the above code returns 13:00 but should return 15:00 – Noosrep Oct 08 '15 at 12:57
  • 1
    Click the link to the documentation. The return is defined as number of milliseconds since 1/1/1970 in the UTC timezone. You want timezones? Look at java.util.Calendar. – John M Oct 12 '15 at 14:34
  • Also note you can use `DateUtils.MILLIS_PER_SECOND` (Apache) or `DateUtils.SECOND_IN_MILLIS` (Android) instead of 1000L to make it a little cleaner. – Hari Ganesan Apr 20 '17 at 17:28
314

Java 8 added a new API for working with dates and times. With Java 8 you can use

import java.time.Instant
...
long unixTimestamp = Instant.now().getEpochSecond();

Instant.now() returns an Instant that represents the current system time. With getEpochSecond() you get the epoch seconds (unix time) from the Instant.

micha
  • 47,774
  • 16
  • 73
  • 80
5

There are two excellent answers already. On the occasion of a new duplicate I am diving a little deeper in two directions:

  1. What to do on java 7?
  2. How to write a testable version?

For Java 7

If you are still using Java 7, you may still choose which of the other answers you want to use. Micha mentions that java.time was introduced in Java 8. But java.time has also been backported to Java 6 and 7 in the ThreeTen Backport. Getting the backport may seem overkill for getting a Unix timestamp, but if you are doing any more date and time work in your program, I still think that you should consider it. There’s a link at the bottom.

Also dividing by 1000 in your own code may seem a very small thing to do. Still I have made it a habit to leave as much date and time work as possible to the standard library, preferably java.time. There are so many other situations where a conversion seems easy but is easy to get wrong. So I don’t want to do them in my code. So my pure Java 7 solution (without an external library/backport) would probably look like this:

    long unixTime = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
    System.out.println(unixTime);

1636883947

Now I am also telling the reader why i am dividing by 1000. While the code is a little bit longer, it is also more self-explanatory.

More testable

java.time also offers a testable solution for both Java 7 and 8 and later. We may inject a Clock, a source of the current time.

    Clock clock = Clock.systemUTC();
    long unixTime = Instant.now(clock).getEpochSecond();
    System.out.println(unixTime);

Output just now:

1636882578

(I ran this on Java 1.7.0_67 using ThreeTen Backport 1.3.6.)

In a test where you need to control which time is used for a reproducible result, for example get a clock with a fixed time:

    Clock clock = Clock.fixed(Instant.ofEpochSecond(1_635_936_963), ZoneOffset.UTC);

Now the output from the code is the time we had specified:

1635936963

If all you want the Clock for is Instants, since Java 17 no longer use Clock. Use InstantSource.

    InstantSource instantSource 
            = InstantSource.fixed(Instant.ofEpochSecond(1_654_321_098));
    long unixTime = instantSource.instant().getEpochSecond();

1654321098

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161