Преобразование метки времени из parse.com в Java

Я получаю метку времени создания объекта от parse.com как 2014-08-01T01:17:56.751Z. У меня есть класс, который преобразует его в относительное время.

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;
}

Проблема в том, что это неправильно разбирает дату. Прямо сейчас результат говорит 4 десятилетия назад, и это очень неправильно. Что я делаю не так?

2 ответа

Решение

Ваш текущий формат даты "yyyy-MM-dd HH:mm:ss" не работает для данного примера 2014-08-01T01:17:56.751Z, В формате отсутствуют символы T а также Z и миллисекунды. Измените это на:

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

починить это.

Также проверьте примеры в JavaDoc SimpleDateFormatпотому что он также показывает правильный формат даты для вашего примера: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html.

Расширяя ответ @ Тома:

Эта проблема

При жестком кодировании "Z" вы предполагаете, что все даты были сохранены как UTC - что не обязательно должно иметь место.

Проблема в том, что SimpleDateFormat не распознает буквальное 'Z' в качестве псевдонима для смещения UTC "-0000" (по какой-либо причине, поскольку он претендует на совместимость с ISO-8601).

Так что вы не можете сделать

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

так как это неправильно предполагает, что все даты будут всегда записываться как в UTC, но вы не можете сделать

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

либо, так как это не сможет проанализировать дату, когда встречается литерал "Z".

Решение 1. Используйте javax.xml.bind.DatatypeConverter

Этот преобразователь типов данных на самом деле соответствует стандарту ISO8601 и может быть использован так же просто, как

import javax.xml.bind.DatatypeConverter;

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

Если вы все равно используете JAXB, это будет путь.

Решение 2. Используйте условные форматы

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();

}

Если вы еще не используете JAXB, вы можете поместить этот метод в служебный класс.

Другие вопросы по тегам