Як конвертувати currentTimeMillis на дату в Java?


140

У мене є кілька мілісекунд у певному файлі журналу, згенерованому на сервері, я також знаю локаль, з якого був створений файл журналу, моя проблема полягає в перетворенні мілісекунд на дату у визначеному форматі. Обробка цього журналу відбувається на сервері, розташованому в іншому часовому поясі. Під час переходу на програму "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, а також правила поводження з аномаліями, такими як літній час.
Василь Бурк

Чи була проблема в тому, що кількість мілісекунд вважалося не від 1970-01-01T00: 00: 00Z, а з якогось іншого моменту?
Василь Бурк

FYI, і страшні старі класи ( GregorianCalendarта SimpleDateFormatін.), І чудова бібліотека Joda -Time тепер витіснені сучасними класами java.time .
Василь Бурк

Відповіді:


115
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!
Саджіб Ачарія

FYI, жахливі старі класи дату, такі як java.util.Date, java.util.Calendarі java.text.SimpleDateFormatтепер застарілі , витіснені класами java.time, вбудованими в Java 8 та новіших версій. Дивіться Підручник від Oracle .
Василь Бурк

2
@SajibAcharya Зверніть увагу, що екземпляри календаря.MONTH починаються з 0; вам потрібно додати один, щоб отримати "справжній" місяць, як ми його знаємо. Приклад: 0 = січень, 1 = лютий, 2 = березень тощо
shagberg

256

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

Date date=new Date(millis);

Ми можемо використовувати пакет java.time (підручник) - API API 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
Набагато ефективніше.
Чад Бінгем

2
Ні. Не всі методи java.util.Dateамортизуються. (Є покращені API для дати та часу в JDK8 java.time)
adatapost

1
@RafaelZeffa, конструктор '' 'Дата (довга дата)' '' не застарів
Gugelhupf

Об'єкт Date надається для зворотної сумісності. Краще використовувати Календар, як було запропоновано вище.
Тон Сной

2
FYI, жахливі старі класи дату, такі як java.util.Date, java.util.Calendarі java.text.SimpleDateFormatтепер застарілі , витіснені класами java.time, вбудованими в Java 8 та новіших версій. Дивіться Підручник від Oracle .
Василь Бурк

24

тл; д-р

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 .

InstantЦе момент на шкалі часу в UTC з дозволом наносекунд . Його епоха - це перший момент 1970 року в UTC.

Якщо припустити, що ваші вхідні дані - це кількість мілісекунд від 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 . І шукайте переповнення стека за багатьма прикладами та поясненнями. Специфікація - 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
    • Пізніші версії реалізації пакетів Android для класів java.time.
    • Для більш раннього Android, то ThreeTenABP проект адаптує ThreeTen-Backport (згаданий вище). Див. Як користуватися ThreeTenABP… .

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


Чи легко було б перетворити рекомендований вище Миттєвий пошук у локальний часовий пояс, який є типовим на пристрої (наприклад, смартфоні)?
AJW

1
@AJW Так. Дзвінок ZoneId.systemDefault(). Дивіться новий розділ, доданий до кінця моєї відповіді.
Василь Бурк

Відмінно, я спробую.
AJW

14

Найпростіший спосіб зробити це - використовувати клас Joda DateTime і вказати як часову позначку в мілісекундах, так і потрібну DateTimeZone.

Я настійно рекомендую уникати вбудованих класів Java Дата та Календар; вони жахливі.


GorgianCalender не працював ... з будь-якої причини потрібен часовий пояс системи за замовчуванням. Джода працював на відмінно.
Аміт

Повідомте мене, дивлячись на зразок коду, якщо ми можемо зробити щось інше з григоріанським
Аміт

1
FYI, проект Joda-Time зараз перебуває в режимі обслуговування , радить переходити до класів java.time . Дивіться Підручник від Oracle .
Василь Бурк

13

Якщо значення мілі є числом мілісів з 1 січня 1970 р. За GMT, як це є стандартним для JVM, то це не залежить від часового поясу. Якщо ви хочете відформатувати його в певному часовому поясі, ви можете просто перетворити його в об’єкт GregorianCalendar і встановити часовий пояс. Після цього існують численні способи її форматування.


1
Це зразок коду з GregorianCalendar та Joda, я отримую правильний вихід з Joda, але не з Gregorian GregorianCalendar календар = новий GregorianCalendar (TimeZone.getTimeZone ("США / Центральний")); Calendar.setTimeInMillis (ваші мільйони секунд); DateTime jodaTime = новий DateTime (ваші мілісекунди, DateTimeZone.forTimeZone (TimeZone.getTimeZone ("US / Central")); DateTimeFormatter parser1 = DateTimeFormat.forPattern ("yyyy-MM-dd HH: mm: ss, SSS");
Аміт

Налаштування часового поясу в об’єкті календаря не спрацювало, але встановив його в об’єкті форматора дати?
Білл

Що таке 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

Найпростіший спосіб:

private String millisToDate(long millis){

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

}

2

Нижче моє рішення отримати дату від мілісекунд до формату дати. Для запуску цього коду вам потрібно використовувати бібліотеку Joda .

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

   }
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.