2013-02-21 3 views
7

У меня есть временная метка типа String, и я пытаюсь преобразовать его в двойной (и найти результат в секундах), и вот что я сделал:Почему SimpleDateFormat.parse(). GetTime() возвращает неверное (отрицательное) значение?

double mytimeStamp = 0; 

String timeStamp = new SimpleDateFormat(" mm ss S").format(new Date()); 

SimpleDateFormat dateFormat = new SimpleDateFormat(" mm ss S"); 

try { 
    mytimeStamp = ((double)dateFormat.parse(timeStamp).getTime())/1000; 
} catch (ParseException e1) { 
    // TODO Auto-generated catch block 
    e1.printStackTrace(); 
} 

System.out.println("timeStamp is: "+ mytimeStamp); 

Проблема заключается в том, что я получаю значение, такое как -2722.515, и я не знаю, почему.

Почему это отрицательно?

С кодом что-то не так?

Когда я конвертирую этот штамп времени в mm ss S, это не соответствует реальному времени, и это, похоже, еще одна проблема!

ответ

11

Это проблема несоответствия часового пояса.

Поскольку вы указали только минуту и ​​секунду, дата будет на 1 Jan 1970 00:mm:ss (mm и ss является указанием минут и секунд текущего времени).

Я упростил свой пример:

String timeStamp = "00 00 00"; 
SimpleDateFormat dateFormat = new SimpleDateFormat("HH mm ss"); 
double hour = dateFormat.parse(timeStamp).getTime()/1000.0/60/60; 
System.out.println("hour is: "+ hour); 

Час распечатанный должен быть GMT «s смещение от местного часового пояса.

Причина этого заключается в том:

SimpleDateFormat локали чувствителен к регистру, поэтому dateFormat.parse(timeStamp) возвратит создать Date объект для данного часового пояса (по умолчанию локальный часовой пояс). Затем getTime() получает количество миллисекунд от midnight 1 Jan 1970 **GMT**. Таким образом, значение будет компенсировано тем, насколько локальный часовой пояс находится от GMT.

Как это исправить:

Вы можете это исправить, установив часовой пояс dateFormat объекта перед parse вызывается следующим образом:

dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 
+0

это вероятно, класс SimpleTimeFormat пытается почтить текущие настройки часового пояса, что потребует перевода времени во что-то перед «1 января 1970 года 00: мм: ss». Поскольку эпоха была бы «после» времени (и там тоже есть двойная броска, которая не помогает), она, вероятно, дрейфует в небольшой диапазон недостоверных значений, что приводит к внешне неверным значениям. Вы можете назвать это ошибкой, но трудно удерживать ее подотчетными за время, выходящее за пределы объявленного эффективного диапазона. –

+0

@ EdwinBuck Edited. – Dukeling

+0

Большое спасибо Dukeling :) он отлично работает сейчас ... – user2052015

1

--- На самом деле есть гораздо лучше способ сделать это, но если вы хотите использовать даты, пропустите предварительный ответ ---

Даты фактически не делают то, что вы хотите, что, по-видимому, вычисляет время вне a ctual необходимо выбрать время от реального мира календарь.

Вам будет намного лучше писать свой собственный класс, чтобы избежать всякой неприятной особой обработки, которую должны выполнять Даты, чтобы идти в ногу с григорианским календарем. Эта специальная обработка включает в себя (но не ограничивается) повышение часовой пояс, летнее время, объявленный «пропущена дни», прыжок секунд, високосный год, и т.д.

public TimeOnly { 

    private long timestamp; 
    private int millis; 
    private int seconds; 
    ... etc ... 

    public TimeOnly(int hours, int minutes, int seconds, int millis) { 
    this.timestamp = millis + seconds * 1000L + minutes * 60000L + hours * 3600000L; 
    this.millis = millis; 
    this.seconds = seconds; 
    ... etc ... 
    } 

    private TimeOnly(long timestamp) { 
    this.timestamp = timestamp; 
    this.millis = timestamp % 1000; 
    this.seconds = timestamp % 60000L - this.millis; 
    ... etc ... 
    } 

    public long getTimestamp() { 
    return timestamp; 
    } 

    public int getMillis() { 
    return millis; 
    } 

    public int getSeconds() { 
    return seconds; 
    } 

    ... etc ... 
} 

public TimeFormatter { 

    public TimeFormatter() { 

    } 

    public String format(Time time) { 
    StringBuilder builder = new StringBuilder(); 
    builder.append(String.valueOf(time.getHours())); 
    builder.append(":"); 
    builder.append(String.valueOf(time.getMinutes())); 
    builder.append(":"); 
    builder.append(String.valueOf(time.getSeconds())); 
    builder.append("."); 
    if (time.getMillis() < 10) { 
     builder.append("00"); 
    } else if (time.getMillis() < 100) { 
     builder.append("0"); 
    } 
    builder.append(time.getMillis()); 
    return builder.toString(); 
} 

Это решение может показаться, что повторно изобретает колесо, но на самом деле это избегает использования восьмиугольника как колеса. Поведение даты не похоже на то, что вы хотите, хотя вы могли бы сделать работу Date для некоторого ограниченного диапазона значений.

Если вы хотите получить действительно фантазию, вы можете сделать вышеуказанное орудие сопоставимым и т. Д. Однако я бы посоветовал на что-то верить. Не предоставляйте методы обновления после построения, так как это приводит к некоторым довольно неприятным перерасчетам и делает код сложнее поддерживать. Вместо этого предоставляйте методы, которые возвращают новые TimeOnlys в ответ на операции, которые вы хотите реализовать.

public TimeOnly addSeconds(int value) { 
    int stamp = this.timestamp; 
    stamp += value * 60000L; 
    if (stamp < timestamp) { 
    throw new Excepton("overflow"); 
    } 
    return new TimeOnly(stamp); 
} 

Кроме того, не реализуйте то, что вы не собираетесь использовать. Неиспользованный код имеет тенденцию быть плодородной почвой для ошибок.

И, конечно же, запасной ответ на все «время», подумайте об использовании JodaTime, который отличает все различные типы измерения времени. Однако, для такой маленькой проблемы, как это, это похоже на использование танков, чтобы убить муравья.

--- Предварительную редактировать ответ ---

Без полной спецификации времени (год, месяц, день, час, минута, секунда, миллисекунды) ваше значение времени в таком формате на первом этапе будет иметь много полей, которые не указаны. То, что происходит в этих областях, скорее всего, будет мусором.

getTime() Затем действует на весь Date объекта переводимого как действительные поля и мусор в значение, где мусор может даже изменить допустимые значения (96 сек = 1 минуту и ​​36 секунд, так как поля взаимодействуют).

Лучший способ пойти об этом, чтобы иметь все свое «время только» Сроки инициализируется один известный день, поэтому, когда вы делаете сравнения и математические операции (это, 3 11 23>1 02 10?) Вы получаете стабильные результаты (да, 3 11 23>1 02 10, потому что это на самом деле 2013 02 10 00 03 11 23>2013 02 10 00 03 11 23 и не 2013 02 10 00 03 11 23 по сравнению с 2000 02 10 00 03 11 23

При выборе дня, чтобы использовать, избегать дней, примыкающие к Feb 29, дни, которые рядом с переходом на летнее сдвиги и т.д.

+0

Когда я делаю это, как вы сказали, я получаю результаты, такие как 1.207806075005E9 , но мне нужно найти его за считанные секунды, а затем вычесть из предыдущей временной метки и, следовательно, Я могу найти продолжительность диалога. – user2052015

Смежные вопросы