简体   繁体   中英

Converting timestamp from parse.com in java

I'm getting my object's createdAt timestamp back from parse.com as 2014-08-01T01:17:56.751Z. I have a class that converts it to relative time.

public static String timeAgo(String time){
  PrettyTime mPtime = new PrettyTime();

  long timeAgo = timeStringtoMilis(time);

  return mPtime.format( new Date( timeAgo ) );
}

public static long timeStringtoMilis(String time) {
  long milis = 0;

  try {
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date   = sd.parse(time);
    milis       = date.getTime();
  } catch (Exception e) {
    e.printStackTrace();
  }

  return milis;
}

The problem is that this parses the date wrongly. Right now the result says 4 decades ago and this very wrong. What I'm I doing wrong?

Your current date format "yyyy-MM-dd HH:mm:ss" does not work for the given example 2014-08-01T01:17:56.751Z . The format is missing the characters T and Z and the milliseconds. Change it to:

new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

to fix it.

Also check the examples in the JavaDoc of SimpleDateFormat , because it also shows the correct date format for your example: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html .

Expanding @Tom's answer:

The problem

When hardcoding 'Z', you assume that all dates were saved as UTC - which doesn't necessarily have to be the case.

The problem is that SimpleDateFormat does not recognize the literal 'Z' as an alias for UTC's '-0000' offset (For whatever reason, since it claims to be ISO-8601 compliant).

So you can't do

new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

since this wrongly assumes all dates will always be written as in UTC, but you can't do

new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

either, since this would not be able to parse the date when the literal 'Z' occurs.

Solution 1: Use javax.xml.bind.DatatypeConverter

This datatype converter actually is ISO8601 compliant and can be used as easy as

import javax.xml.bind.DatatypeConverter;

public Long isoToMillis(String dateString){
  Calendar calendar = DatatypeConverter.parseDateTime(dateString);
  return calendar.getTime().getTime();
}

If you use JAXB anyway, that would be the way to go.

Solution 2: Use conditional formats

final static String ZULUFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
final static String OFFSETFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

/* This is a utility method, so you want the calling method
 * to be informed that something is wrong with the input format
 */
public static Long isoToMillis(String dateString) throws ParseException{

  /* It is the default, so we should use it by default */
  String formatString = ZULUFORMAT;

  if(! dateString.endsWith("Z") ) {
    formatString = OFFSETFORMAT;
  }

  SimpleDateFormat sd = new SimpleDateFormat(formatString);
  return sd.parse(dateString).getTime();

}

If you don't already use JAXB, you might want to put this method into a utility class.

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