Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert UTC date into milliseconds

I am not interested in what the current UTC time is in milliseconds, nor do I need to mess with timezones. My original date is already stored as a UTC timestamp.

I have a date stored in a database in UTC time, "2012-06-14 05:01:25". I am not interested in the datetime, but just the date portion of the it. So, after retrieving the date in Java, and excluding the hours, minutes, and seconds - I am left with "2012-06-14".

How can I convert this into UTC milliseconds?

like image 283
Tyrick Avatar asked Aug 22 '12 21:08

Tyrick


People also ask

How do you convert date to milliseconds?

This is the number of seconds since the 1970 epoch. To convert seconds to milliseconds, you need to multiply the number of seconds by 1000. To convert a Date to milliseconds, you could just call timeIntervalSince1970 and multiply it by 1000 every time.

How do you convert timestamps to milliseconds?

Using timedelta. A simple solution is to get the timedelta object by finding the difference of the given datetime with Epoch time, i.e., midnight 1 January 1970. To obtain time in milliseconds, you can use the timedelta. total_seconds() * 1000 .

How do I convert date to milliseconds in Excel?

If you need milliseconds, you need to add a further multiplication / division by 1000. For example, converting from epoch time (milliseconds) to a date would be "=((((A1/1000)/60)/60)/24)+DATE(1970,1,1)".

How do you find time in milliseconds?

To get the current time in milliseconds, you just need to convert the output of Sys. time to numeric, and multiply by 1000.


3 Answers

EDIT: I'd missed the "ignoring the time of day" part. It's now present, but near the end...

The simplest approach is probably to use SimpleDateFormat, having set the time zone appropriately:

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));

Date date = format.parse(text);
long millis = date.getTime();

(Setting the time zone is the important bit here, as otherwise it will interpret the value to be in the local time zone.)

Alternatively, if you're doing anything less trivial than this, use Joda Time which is a much better date/time API. In particular, SimpleDateFormat isn't thread-safe whereas DateTimeFormatter is:

// This can be reused freely across threads after construction.
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
    .withLocale(Locale.US)
    .withZoneUTC();

// Option 1
DateTime datetime = formatter.parseDateTime(text);
long millis = dateTime.getMillis();

// Option 2, more direct, but harder to diagnose errors
long millis = formatter.parseMillis(text);

Now so far, we've parsed the whole whole caboodle. The easiest way of ignoring the date part is just to round it off - after all, Java doesn't observe leap seconds, so we can just truncate it:

long millisPerDay = 24L * 60L * 60L * 1000L; // Or use TimeUnit
long dayMillis = (millis / millisPerDay) * millisPerDay;

That will "round towards 1970" so if you have a date before 1970 it will round to the end of the day - but I suspect that's unlikely to be a problem.

With the Joda Time version you could just use this instead:

DateTime dateTime = formatter.parseDateTime(text);
long millis = dateTime.toLocalDate().getLocalMillis();

I would personally not go with the idea of just taking a substring. Even though you're not actually interested in preserving the hour/minute/second, I think it's appropriate to parse what you've been given and then throw away information. Aside from anything else, it makes your code fail appropriately with bad data, e.g.

"2012-06-100"

or

"2012-06-14 25:01:25"

indicate problems in whatever's supplying you data, and it's good to spot that rather than to continue blindly just because the first 10 characters are okay.

like image 57
Jon Skeet Avatar answered Oct 12 '22 11:10

Jon Skeet


java.time and JDBC 4.2

I am providing the modern answer. These days (and for the last several years) you should use java.time, the modern Java date and time API, for your date and time work. And since JDBC 4.2 you can directly retrieve java.time objects from your database (and also store them into it). A modern JPA implementation (Hibernate at least since Hibernate 5) will be happy to do the same. So forget about SimpleDateFormat, Date and other old classes used in most of the old answers. The mentioned ones are poorly designed, and java.time is so much nicer to work with.

Retrieve proper date-time objects from your database

I also recommend that you don’t retrieve your UTC time as a string from the database. If the datatype in SQL is timestamp with time zone (recommended for UTC times), retrieve an OffsetDateTime. For example:

    PreparedStatement pStmt = yourDatabaseConnection
            .prepareStatement("select utc_time from your_table where id = 7;");
    ResultSet rs = pStmt.executeQuery();
    if (rs.next()) {
        OffsetDateTime utcDateTime = rs.getObject("utc_time", OffsetDateTime.class);
        long millisecondsSinceEpoch = utcDateTime.truncatedTo(ChronoUnit.DAYS)
                .toInstant()
                .toEpochMilli();
        System.out.println("Milliseconds since the epoch: " + millisecondsSinceEpoch);
    }

If the type in SQL is dateTime or timestamp without time zone, we probably need to retrieve a LocalDateTime instead (details depending on your JDBC driver and the time zone of your database session). It goes in the same manner. For converting your LocalDateTime to OffsetDateTime, see the conversion below.

If you need to convert from a string

If you cannot avoid getting your UTC time as a string as in the question, parse it into a LocalDateTime and convert from there. For example:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
    String utcTimeString = "2012-06-14 05:01:25";
    long millisecondsSinceEpoch = LocalDateTime.parse(utcTimeString, formatter)
            .atOffset(ZoneOffset.UTC)
            .toInstant()
            .toEpochMilli();
    System.out.println("Milliseconds since the epoch: " + millisecondsSinceEpoch);

Output:

Milliseconds since the epoch: 1339650085000

Link

  • Oracle tutorial: Date Time explaining how to use java.time.
like image 45
Ole V.V. Avatar answered Oct 12 '22 12:10

Ole V.V.


UPDATE: See the modern solution using java.time classes in the correct Answer by Ole V.V..

Simpler

The answer by Jon Skeet is correct. And he makes a good point about including, rather than truncating, the time-of-day info while parsing.

However, his code could be simplified. Especially so because Joda-Time gained an important new method in the latest versions: withTimeAtStartOfDay. This method supplants all the "midnight"-related classes and methods which are now deprecated.

Specifying a Locale is a good habit, as shown in his code. But in this particular case a Locale is not necessary.

His answer correctly suggests the Joda-Time library, far superior to using java.util.Date, .Calendar, and java.text.SimpleTextFormat. Those classes are notoriously troublesome, and should be avoided. Instead use either Joda-Time or the new java.time package built into Java 8 (inspired by Joda-Time, defined by JSR 310).

First Moment Of The Day

You cannot ignore time-of-day if what you want is a count of milliseconds-since-epoch. I suspect what you want is to change the time to first moment of the day. In UTC, this always means the time 00:00:00.000. But note that in local time zones, the first moment may be a different time because of Daylight Saving Time and possibly other anomalies.

ISO 8601

Your string is nearly in standard ISO 8601 format, but we need to swap a T for the SPACE in the middle. Then we can feed the resulting string directly to Joda-Time as Joda-Time has built-in formatters used by default for standard strings.

Example Code

The following example code assumes the intent of your question is to parse a string as a date-time value in UTC time zone, adjust the time to the first moment of the day, and then convert to number of milliseconds since Unix epoch (beginning of 1970 in UTC).

String inputRaw = "2012-06-14 05:01:25";
String input = inputRaw.replace( " ", "T" );  // Replace SPACE with a 'T'.
DateTime dateTime = new DateTime( input, DateTimeZone.UTC );  // Parse, assuming UTC.
DateTime dateTimeTopOfTheDay = dateTime.withTimeAtStartOfDay();  // Adjust to first moment of the day.
long millisecondsSinceUnixEpoch = dateTimeTopOfTheDay.getMillis();  // Convert to millis. Use a 'long', not an 'int'.
like image 37
Basil Bourque Avatar answered Oct 12 '22 11:10

Basil Bourque