bluecricket
bluecricket

Reputation: 2042

Epoch Timestamp String to Joda Datetime using ONLY String Formatter

Assuming I have a timestamp "1355409000003" as a String, is there a way to specify a DateTime format that parses that into a Joda DateTime?

I.e., I can parse "12/01/2012" with format "MM/dd/YYYY" and "2012-12-01 04:27" with "YYYY-MM-dd HH:mm", but how can I parse "1355409000003"?

edit: not using a different constructor, assume I MUST specify a String format to parse with

Upvotes: 6

Views: 6383

Answers (1)

Basil Bourque
Basil Bourque

Reputation: 339917

tl;dr

Just parse your String to long. No big deal.

Use java.time classes that supplant Joda-Time project.

Instant.ofEpochMilli( 
    Long.parseLong( "1355409000003" ) 
)

2012-12-13T14:30:00.003Z

Parse String to long

Your Question does not really make sense. If you get a string representing the count of milliseconds since epoch of 1970-01-01T00:00Z, then convert that String to a long and pass to the constructor of the Joda-Time DateTime type.

This was shown in an Answer that was inexplicably deleted.

DateTime dt = new DateTime( Long.parseLong( "1355409000003" ) ) ;

Or, personally, I would separate onto two lines.

long millisSinceEpoch = Long.parseLong( "1355409000003" ) ;
DateTime dt = new DateTime( millisSinceEpoch ) ;

You posted this Comment to that Question:

unfortunately, the structure by which these timestamps are being consumed does not lend itself to using a different constructor - assuming I am REQUIRED to specify a string format, is there a format that parses epoch timestamps?

Again, your insistence on a constructor taking a String is nonsensical, as it is simple to the point of being trivial to wrap your textual number with a parsing call: Long.parseLong( "1355409000003" ). Don’t make a mountain out of a molehill.

java.time

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

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Same approach here with java.time as seen above with Joda-Time: Parse the String to a long, and use the number to get an Instant object (rather than a DateTime object).

The java.time classes avoid constructors. So, instead of calling a constructor, call the static factory method Instant.ofEpochMilli.

long millisSinceEpoch = Long.parseLong( "1355409000003" ) ;
Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;

Custom method

If the issue prompting your insistence is that this occurs throughout your code, and you want to avoid littering your codebase with all the extra Long.parseLong(, then you could make your own utility method to encapsulate this string-to-long conversion.

I am not recommending this as it seems like overkill. But if you insist, here is some example code.

package com.basilbourque.example;

import java.time.Instant;

public class InstantMaker
{
    static public Instant parseMillis ( String countOfMillisecondsSinceEpoch )
    {
        // TODO - Add code to test for invalid inputs, trap for exception thrown.
        long millis = Long.parseLong( countOfMillisecondsSinceEpoch );
        Instant instant = Instant.ofEpochMilli( millis);
        return instant;
    }

    // Constructor. Hide the default constructor as "private". We have no need for instances here.
    private InstantMaker ( )
    {
    }

    // `main` method for testing ad demonstration.
    public static void main ( String[] args )
    {
        Instant instant = InstantMaker.parseMillis( "1355409000003" );
        System.out.println( instant );
    }
}

If this is your concern, I suggest the real problem is relying on a count-from-epoch regardless of whether it is textual or numeric. A count-from-epoch makes date-time handling much more difficult as the values cannot be discerned by humans. This makes troubleshooting, debugging, and logging tricky and unnecessarily complicated. I would suggest refactoring your code to be passing around Instant instances rather than strings like "1355409000003".

ISO 8601

If you must serialize date-time values to text, use only the standard ISO 8601 formats. That is the primary purpose for the standard, exchanging date-time values between systems. The formats are designed to be practical and sensible, easy to parse by machine yet easy to read by humans across cultures.

The java.time classes use the standard ISO 8601 formats by default when parsing/generating strings. You can see examples of such strings above in this Answer.


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.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

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.

Upvotes: 3

Related Questions