Как рассчитать миллисекунды с помощью Java, как в Ruby?

Я могу рассчитать время в миллисекундах с помощью следующего фрагмента Ruby:

$ irb
> require 'date'
 => true 
> Date.new(2014,9,5).to_time
 => 2014-09-05 00:00:00 +0200
> Date.new(2014,9,5).to_time.to_i * 1000
 => 1409868000000

1409868000000 — это желаемый результат.
Как получить такой же результат с помощью Java? Я установил часовой пояс на CEST, так как кажется, что Руби работает с. Итак, я попробовал это:

GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("CEST"));
calendar.set(2014, 9, 5);
System.out.println("" + calendar.getTimeInMillis());
// Returns: 1412498241422

person JJD    schedule 22.08.2014    source источник


Ответы (4)


В вашем текущем коде есть три проблемы:

  • «CEST» не является часовым поясом, распознаваемым Java. Вместо этого попробуйте Europe/Paris в качестве европейского часового пояса.
  • java.util.Calendar использует месяцы с отсчетом от 0 (да, это ужасно)
  • Вы не очистили временную часть Calendar, поэтому она даст вам текущее время дня в этот день.

Это работает:

import java.util.*;

public class Test {
    public static void main(String[] args) throws Exception {
        TimeZone zone = TimeZone.getTimeZone("Europe/Paris");
        Calendar calendar = new GregorianCalendar(zone);
        // Month 8 = September in 0-based month numbering
        calendar.set(2014, 8, 5, 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        System.out.println(calendar.getTimeInMillis());
    }
}

Если вы знаете месяц заранее, вы можете вместо этого использовать константы:

calendar.set(2014, Calendar.SEPTEMBER, 5, 0, 0, 0);

Однако, если вы можете перейти на использование Joda Time или java.time из Java 8, это гораздо более чистые API.

Например, в Joda Time:

import org.joda.time.*;

class Test {
    public static void main(String[] args) {
        DateTimeZone zone = DateTimeZone.forID("Europe/Paris");
        // Look ma, a sensible month numbering system!
        LocalDate date = new LocalDate(2014, 9, 5);
        DateTime zoned = date.toDateTimeAtStartOfDay(zone);
        System.out.println(zoned.getMillis());
    }
}
person Jon Skeet    schedule 22.08.2014
comment
Просто повторюсь, потому что связь между списком и первым фрагментом может быть потеряна: пример Джона устанавливает дату объекта календаря на 5 сентября 2014 года. Месяцы с отсчетом от 0. - person hiergiltdiestfu; 22.08.2014
comment
Я начинаю кампанию, чтобы заставить его использовать дни с нулевым отсчетом в Java 9 :) - person chiastic-security; 22.08.2014
comment
@hiergiltdiestfu: Спасибо - я обновил ответ, чтобы сделать его немного яснее. - person Jon Skeet; 22.08.2014

java.время

API даты и времени java.util и их API форматирования SimpleDateFormat устарели и подвержены ошибкам. Рекомендуется полностью прекратить их использование и перейти на современный API Date-Time*, выпущенный в марте 2014 г.

Кроме того, ниже приводится уведомление на главной странице Joda-Time:

Обратите внимание, что начиная с Java SE 8 пользователям предлагается перейти на java.time (JSR-310) — основную часть JDK, которая заменяет этот проект.

Решение с использованием java.time, современного API даты и времени:

import java.time.LocalDate;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {    

        long millis = LocalDate.of(2014, 9, 5)
                                .atStartOfDay(ZoneId.of("Europe/Paris"))
                                .toInstant()
                                .toEpochMilli();
        
        System.out.println(millis);
    }
}

Вывод:

1409868000000

ОНЛАЙН-ДЕМО

Избегайте использования двух/трех/четырехбуквенных сокращений для названия часового пояса. Используйте условное обозначение «Регион/город», например. Europe/Paris. Вы можете получить список названий часовых поясов, используя ZoneId.getAvailableZoneIds().

Узнайте больше о современном API Date-Time на странице Trail: Date Time< /а>.


* По какой-либо причине, если вам нужно придерживаться Java 6 или Java 7, вы можете использовать ThreeTen-Backport, который переносит большую часть функций java.time на Java 6 и 7. Если вы работаете над проектом Android и ваш уровень Android API по-прежнему не соответствует Java-8, проверьте Java 8+ API доступно через дешугаринг и Как использовать ThreeTenABP в Android Project.

person Arvind Kumar Avinash    schedule 10.06.2021

Вы можете использовать System.currentTimeMillis(), чтобы получить время в миллисекундах с начала эпохи.

Если вы хотите перевести на ту же базовую линию, которую использует Ruby, это будет так же просто, как добавить некоторое фиксированное смещение (т. е. использовать System.currentTimeMillis() + DELTA). Вы должны быть в состоянии вычислить DELTA, попробовав его в Ruby и в Java в какой-то фиксированный день, чтобы увидеть, в чем разница.

Вы уверены, что вычисления Ruby не зависят от локали? Было бы странно (если не сказать правдоподобно), если бы он регулярно использовал CEST.

person chiastic-security    schedule 22.08.2014

пытаться

calendar.set(2014, 8, 5, 0, 0, 0);
System.out.println("" + (calendar.getTimeInMillis() / 1000) * 1000);

см. http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#set(int,%20int,%20int,%20int,%20int)

person Scary Wombat    schedule 22.08.2014