Как преобразовать currentTimeMillis в дату в Java?

145

У меня есть миллисекунды в определенном файле журнала, сгенерированном на сервере, я также знаю локаль, из которой был создан файл журнала, моя проблема состоит в том, чтобы преобразовать миллисекунды на дату в указанном формате. Обработка этого журнала происходит на сервере, расположенном в другом часовом поясе. При преобразовании в "SimpleDateFormat" программа принимает дату машины, поскольку такая форматированная дата не соответствует правильному времени сервера. Есть ли способ сделать это элегантно?

long yourmilliseconds = 1322018752992l;
        //1322018752992-Nov 22, 2011 9:25:52 PM 

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS",Locale.US);

GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("US/Central"));
calendar.setTimeInMillis(yourmilliseconds);

System.out.println("GregorianCalendar -"+sdf.format(calendar.getTime()));

DateTime jodaTime = new DateTime(yourmilliseconds, 
                    DateTimeZone.forTimeZone(TimeZone.getTimeZone("US/Central")));
DateTimeFormatter parser1 = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss,SSS");

System.out.println("jodaTime "+parser1.print(jodaTime));

Выход:

Gregorian Calendar -2011-11-23 08:55:52,992
jodaTime 2011-11-22 21:25:52,992
Амит
источник
Не путайте языковой стандарт с часовым поясом. Совершенно отдельно. Локаль определяет человеческий язык для названия месяцев и дней, а также культурных норм, таких как порядок частей, таких как месяц, день и т. Д. Часовой пояс - это смещение от UTC плюс правила для обработки аномалий, таких как переход на летнее время.
Basil Bourque
Была ли проблема в том, что количество миллисекунд было отсчетом не из 1970-01-01T00: 00: 00Z, а из какого-то другого момента?
Basil Bourque
К вашему сведению, как ужасные старые классы даты и времени ( GregorianCalendar, SimpleDateFormatи т. Д.), Так и превосходная библиотека Joda-Time теперь вытеснены современными классами java.time .
Basil Bourque

Ответы:

119
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeStamp);

int mYear = calendar.get(Calendar.YEAR);
int mMonth = calendar.get(Calendar.MONTH);
int mDay = calendar.get(Calendar.DAY_OF_MONTH);
Фейсал Ашраф
источник
Мне пришлось установить Календарь как окончательный, чтобы он работал. final Calendar calendar = Calendar.getInstance();
Виктор Аугусто
4
Объекты календаря обычно считаются довольно большими, поэтому по возможности их следует избегать. Объект Date будет лучше, если у него есть необходимая вам функциональность. "Дата дата = новая дата (миллисекунды);" предоставленный в другом ответе пользователя AVD, будет лучшим маршрутом :)
Дик Лукас
1
Каким-то образом 1515436200000lя получаю calendar.get(Calendar.MONTH))как 0!
Саджиб Ачарья 06
К вашему сведению, ужасно неприятные старые классы даты и времени, такие как java.util.Date, java.util.Calendarи java.text.SimpleDateFormat, теперь унаследованы , вытеснены классами java.time, встроенными в Java 8 и новее. См. Учебник Oracle .
Basil Bourque
2
@SajibAcharya Обратите внимание, что экземпляры для Calendar.MONTH начинаются с 0; вам нужно добавить один, чтобы получить "настоящий" месяц, как мы его знаем. Пример: 0 = январь, 1 = февраль, 2 = март и т. Д.
shagberg
258

Вы можете использовать java.util.Dateкласс, а затем использовать его SimpleDateFormatдля форматирования Date.

Date date=new Date(millis);

Мы можем использовать пакет java.time (учебник) - API DateTime, представленные в Java SE 8.

var instance = java.time.Instant.ofEpochMilli(millis);
var localDateTime = java.time.LocalDateTime
                        .ofInstant(instance, java.time.ZoneId.of("Asia/Kolkata"));
var zonedDateTime = java.time.ZonedDateTime
                            .ofInstant(instance,java.time.ZoneId.of("Asia/Kolkata"));

// Format the date

var formatter = java.time.format.DateTimeFormatter.ofPattern("u-M-d hh:mm:ss a O");
var string = zonedDateTime.format(formatter);
адатапост
источник
2
Намного эффективнее.
Chad Bingham
2
Неа. Не все методы java.util.Dateамортизируются. (В JDK8 есть улучшенные API даты и времени java.time)
adatapost
1
@RafaelZeffa, конструктор '' 'Date (long date)' '' не устарел
Gugelhupf
Объект Date предоставляется для обратной совместимости. Лучше использовать Календарь, как предложено выше.
Ton Snoei
2
К вашему сведению, ужасно неприятные старые классы даты и времени, такие как java.util.Date, java.util.Calendarи java.text.SimpleDateFormat, теперь унаследованы , вытеснены классами java.time, встроенными в Java 8 и новее. См. Учебник Oracle .
Basil Bourque
24

tl; dr

Instant.ofEpochMilli( 1_322_018_752_992L )     // Parse count of milliseconds-since-start-of-1970-UTC into an `Instant`.
       .atZone( ZoneId.of( "Africa/Tunis" ) )  // Assign a time zone to the `Instant` to produce a `ZonedDateTime` object.

Детали

В других ответах используются устаревшие или неправильные классы.

Избегайте старых классов даты и времени, таких как java.util.Date/.Calendar. Они оказались плохо спроектированными, запутанными и неудобными.

java.time

Java.time рамки поставляется встроенный в Java 8 и более поздних версий. Большая часть функциональности перенесена на Java 6 и 7 и в дальнейшем адаптирована для Android . Сделано теми же людьми, что и Joda-Time .

An Instant- это момент на временной шкале в формате UTC с разрешением наносекунды . Его эпоха - первый момент 1970 года по всемирному координированному времени.

Предполагая, что ваши входные данные представляют собой количество миллисекунд с 1970-01-01T00: 00: 00Z (не ясно в вопросе), тогда мы можем легко создать экземпляр файла Instant.

Instant instant = Instant.ofEpochMilli( 1_322_018_752_992L );

Instant.toString (): 2011-11-23T03: 25: 52.992Z

ZВ этом стандарте ISO 8601 отформатированной строки является аббревиатурой Zuluи означает UTC .

Примените часовой пояс, используя правильное имя часового пояса , чтобы получить расширение ZonedDateTime.

ZoneId zoneId = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( zoneId );

Посмотрите, как этот код запускается вживую на IdeOne.com .

Asia/Kolkata часовой пояс ?

Я предполагаю, что у вас есть часовой пояс Индии, влияющий на ваш код. Здесь мы видим, что при настройке на Asia/Kolkataчасовой пояс отображается то же время суток, что и в сообщении, 08:55что на пять с половиной часов опережает наше значение UTC 03:25.

2011-11-23T08: 55: 52.992 + 05: 30 [Азия / Калькутта]

Зона по умолчанию

Вы можете применить текущий часовой пояс JVM по умолчанию . Помните, что значение по умолчанию может измениться в любой момент во время выполнения . Любой код в любом потоке любого приложения в JVM может изменить текущее значение по умолчанию. Если важно, спросите у пользователя желаемый / ожидаемый часовой пояс.

ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

О java.time

Java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытеснять неприятные старые устаревшие классы даты и времени , такие как java.util.Date, Calendar, и SimpleDateFormat.

Проект Joda-Time , находящийся сейчас в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial . И поищите в Stack Overflow множество примеров и объяснений. Спецификация - JSR 310 .

С драйвером JDBC , совместимым с JDBC 4.2 или новее, вы можете обмениваться объектами java.time напрямую с вашей базой данных. Нет необходимости в строках или классах java.sql. *.

Где взять классы java.time?

  • Java SE 8 , Java SE 9 и более поздние версии
    • Встроенный.
    • Часть стандартного Java API со встроенной реализацией.
    • В Java 9 добавлены некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport .
  • Android

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательной площадкой для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь , такие как Interval, YearWeek, YearQuarter, и более .

Василий Бурк
источник
Было бы легко преобразовать Instant, который вы рекомендуете выше, в местный часовой пояс, который используется по умолчанию на устройстве (например, смартфоне)?
AJW
1
@AJW Да. Звоните ZoneId.systemDefault(). Смотрите новый раздел, добавленный в конец моего ответа.
Basil Bourque
Отлично, я попробую.
AJW
14

Самый простой способ сделать это - использовать класс Joda DateTime и указать как временную метку в миллисекундах, так и желаемую DateTimeZone .

Я настоятельно рекомендую избегать встроенных классов Java Date и Calendar; они ужасны.

Кэмерон Скиннер
источник
GorgianCalender не работал ... по какой-то причине он использовал часовой пояс системы по умолчанию. Джода работал отлично.
Амит
Дайте мне знать, глядя на пример кода, если мы можем сделать что-то другое с григорианским
языком
1
К вашему сведению, проект Joda-Time сейчас находится в режиме обслуживания , предлагая перейти на классы java.time . См. Учебник Oracle .
Basil Bourque
13

Если значение в миллисекундах - это количество миллисекунд с 1 января 1970 года по Гринвичу, что является стандартом для JVM, то это не зависит от часового пояса. Если вы хотите отформатировать его с использованием определенного часового пояса, вы можете просто преобразовать его в объект GregorianCalendar и установить часовой пояс. После этого есть множество способов отформатировать его.

Билл
источник
1
Это пример кода с GregorianCalendar и Joda, я получаю правильный вывод с помощью Joda, но не с помощью Gregorian GregorianCalendar calendar = new GregorianCalendar (TimeZone.getTimeZone ("US / Central")); calendar.setTimeInMillis (ваши миллисекунды); DateTime jodaTime = new DateTime (yourmilliseconds, DateTimeZone.forTimeZone (TimeZone.getTimeZone ("США / Центральный"))); DateTimeFormatter parser1 = DateTimeFormat.forPattern ("гггг-ММ-дд ЧЧ: мм: сс, SSS");
Амит
Установка часового пояса в объекте календаря не сработала, но установка его в объекте форматирования даты сработала?
Bill
Что такое DateTime и DateTimeFormatter ??
SweetWisher ツ
11

Мое решение

public class CalendarUtils {

    public static String dateFormat = "dd-MM-yyyy hh:mm";
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);

    public static String ConvertMilliSecondsToFormattedDate(String milliSeconds){
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(Long.parseLong(milliSeconds));
        return simpleDateFormat.format(calendar.getTime());
    }
}
Сиддарт Канант
источник
6

Я так делаю:

static String formatDate(long dateInMillis) {
    Date date = new Date(dateInMillis);
    return DateFormat.getDateInstance().format(date);
}

Вы также можете использовать getDateInstance(int style)со следующими параметрами:

DateFormat.SHORT

DateFormat.MEDIUM

DateFormat.LONG

DateFormat.FULL

DateFormat.DEFAULT

Йогеш Умеш Вайти
источник
5

Класс SimpleDateFormat имеет метод SetTimeZone (TimeZone), унаследованный от класса DateFormat. http://docs.oracle.com/javase/6/docs/api/java/text/DateFormat.html

Джессика Браун
источник
К вашему сведению, эти ужасные классы теперь заменены современными классами java.time после принятия JSR 310.
Бэзил Бурк,
5

Самый простой способ:

private String millisToDate(long millis){

    return DateFormat.getDateInstance(DateFormat.SHORT).format(millis);
    //You can use DateFormat.LONG instead of SHORT

}
Хоакин Юрчук
источник
2

Ниже представлено мое решение для получения даты в формате от миллисекунд до даты. Вы должны использовать Joda Library, чтобы запустить этот код.

import java.util.GregorianCalendar;
import java.util.TimeZone;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class time {

    public static void main(String args[]){

        String str = "1431601084000";
        long geTime= Long.parseLong(str);
        GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("US/Central"));
        calendar.setTimeInMillis(geTime);
        DateTime jodaTime = new DateTime(geTime, 
               DateTimeZone.forTimeZone(TimeZone.getTimeZone("US/Central")));
        DateTimeFormatter parser1 = DateTimeFormat.forPattern("yyyy-MM-dd");
        System.out.println("Get Time : "+parser1.print(jodaTime));

   }
}
Archit
источник
2

Вы можете попробовать java.time api;

        Instant date = Instant.ofEpochMilli(1549362600000l);
        LocalDateTime utc = LocalDateTime.ofInstant(date, ZoneOffset.UTC);
Нарендар Редди М
источник