2015-09-10 4 views
3

Я ищу способ, способный к созданию Java 6 Секунд с эпохи в GMT/UTC (также известный как отметка времени UNIX) из объекта java.sql.Date.Быстрая реализация Java 6 для получения отметки времени UNIX в GMT

Мой Java 8 код:

Long seconds = dateObject.toLocalDate().atStartOfDay(ZoneId.of("GMT")).toEpochSecond() 

Мой Java 6 код:

final Calendar cal = Calendar.getInstance(); 
cal.setTime(dateObject); 
final int year = cal.get(Calendar.YEAR); 
final int month = cal.get(Calendar.MONTH); 
final int day = cal.get(Calendar.DAY_OF_MONTH); 

final GregorianCalendar c = new GregorianCalendar(); 
c.clear(); 
c.setGregorianChange(new Date(Long.MIN_VALUE)); 
c.setTimeZone(TimeZone.getTimeZone("GMT")); 
c.set(Calendar.YEAR, year); 
c.set(Calendar.MONTH, month); 
c.set(Calendar.DAY_OF_MONTH, day); 

Long seconds = c.getTimeInMillis()/1000 

Unfortunally, код Java 6 составляет примерно как половина так же быстро, как код Java 8. У меня было решение Java 6 с меньшим количеством кода в прошлом (и тем самым быстрее), но это было неправильно, когда дело доходило до необычных дат как «0001-01-01», где требуется setGregorianChange(), а второй GergorianCalendar.

Любая идея, что я могу сделать, чтобы быстро реализовать Java 6?

  1. мне нужна безопасность Thread
  2. "2010-01-01" должно привести к 1262304000
  3. "0001-01-01" должно привести к -62135596800
  4. "2999-12-31" должен в результате 32503593600

EDIT 1

Я также попытался следующие Java 6 код:

final TimeZone tz = TimeZone.getDefault(); 
Long seconds = (dateObject.getTime() + tz.getRawOffset())/1000; 

Это работает с "2010-01-01" и "2999-12-31", но не с "0001-01-01" (ожидается: -62135596800, фактический: -62135769600) - догадайтесь недостатком «setGregorianChange» является то, что неприятности здесь.

РЕДАКТИРОВАТЬ 2

Код работает в JsonSerializer. У меня есть приложение, представляющее эти временные метки UNIX внутри JSON. Сторона-потребитель ожидает отметки времени как отметки времени по Гринвичу и создаст дату по этим временным шкафам, жестко привязывающим часовой пояс к GMT, но используя его позже, как там, где местный часовой пояс.

Чтобы сделать проблему более понятной, я приведу пример.

  • Дата на моей стороне: 2010-01-01 (UTC + 100)
  • миллисекунды: 1262300400000
  • секунд: 1262300400

потребитель теперь занимает это секунд и формирует дату из из него:

  • чт, 31 декабря 2009 23:00:00 GMT

Конечно - это на 100% верно, но потребитель использует эту дату, как если бы она находилась в локальном часовом поясе ...

Секунды, которые, как я предполагаю, будут перенесены, - 1262300400 + 3600 (мой TZ Offset) для этого примера.

EDIT 3

Я получил GregorianCalendar -thing вниз к 4liner - но даже это гораздо медленнее, чем Java 8 вещь. Проблема заключается в создании нового объекта GregorianCalendar каждый раз, когда выполняется код. Но это обязательный факт, поскольку Calendar не является потоковым. Таким образом, быстрое решение должно каким-то образом работать без какого-либо объекта-инстанцирования. Пример ниже в основном похож на EDIT 1 и даже быстрее, чем код Java 8. Он просто не работает правильно с датами до юлианско -> григорианского переключателя (15 октября - 1582).

public class UnixTimestampSerializer extends JsonSerializer<Date> { 

    @Override 
    public void serialize(final Date dateObject, final JsonGenerator jgen, final SerializerProvider provider) 
      throws IOException, JsonProcessingException { 
     jgen.writeNumber((dateObject.getTime() - dateObject.getTimezoneOffset() * 60 * 1000)/1000) 
    } 
} 

Unfortunally он работает) с устаревшим методом и б) правильно не работает с датами, прежде чем 1582 :(. Использование статического TimeZone.getDefault().getRawOffset() для решения а) не вариант, так как TimeZone может измениться (лето - против зимы) на каждую дату.

+2

Я хочу быть «тот парень» и спросить, если вы пробовали время Joda http://www.joda.org/joda-time? –

+1

Почему вы получаете экземпляр календаря и продолжаете создавать * другой * GregorianCalendar, полностью игнорируя полученный ранее календарь. Начните с удаления мертвого кода? – Durandal

+0

@ DamienO'Reilly - Я хочу решение без каких-либо зависимостей. – Olli

ответ

0

Я не знаю, что было бы быстрее, чем использование currentTimeInMillis и преобразование в секунды. Это вернется в секундах от EPOCH, это должно быть довольно быстро. Использование объекта Date кажется мне ненужным.

 BigDecimal seconds = BigDecimal.valueOf(System.currentTimeMillis()/1000.0); 
     System.out.println(seconds); 
+0

Мне нужен GMT.Это приведет к секундам с эпохи в локальном часовом поясе – Olli

+0

Но тогда вы не могли бы просто добавить часовую разницу в часовом поясе? –

+0

Да - имел ту же идею несколько секунд назад. Хороший улов;) Но - он не работает в таких датах, как 0001-01-01, поскольку изменение по умолчанию от юлианского к григорианскому календарю дает проблемы здесь. Не знаю, когда java предполагает Джулиана - может быть, до 1582 года? Я не знаю. Но это вызывает проблемы в моем случае. Для этого я отредактировал свою начальную публикацию. – Olli

3
java.sql.Date date = ...; 
long unixTimestamp = date.getTime()/1000; 
+0

вопрос был: * GMT * – Olli

+2

Количество секунд между Epoch и некоторым моментом времени ('date') не зависит от часовых поясов. – Roman

+0

Эпоха имеет часовой пояс, а 'date' также имеет часовой пояс ... - Я предполагаю, что проблема в том, что он должен гарантировать, что у них одинаковые (GMT). –