Преобразование даты / времени для данного часового пояса - java

80

Я хочу преобразовать эту метку времени GMT в GMT + 13:

2011-10-06 03:35:05

Я пробовал около 100 различных комбинаций DateFormat, TimeZone, Date, GregorianCalendar и т.д., чтобы попытаться выполнить эту ОЧЕНЬ простую задачу.

Этот код делает то, что я хочу в ТЕКУЩЕЕ ВРЕМЯ:

Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");    
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));  

String newZealandTime = formatter.format(calendar.getTime());

Но я хочу установить время, а не использовать текущее время.

Я обнаружил, что каждый раз, когда я пытаюсь установить время следующим образом:

calendar.setTime(new Date(1317816735000L));

используется часовой пояс локального компьютера. Это почему? Я знаю, что когда «new Date ()» возвращает время UTC + 0, почему, когда вы устанавливаете время в миллисекундах, он больше не предполагает, что время находится в UTC?

Это возможно:

  1. Установите время на объекте (Calendar / Date / TimeStamp)
  2. (Возможно) Установите часовой пояс начальной отметки времени (calendar.setTimeZone (...))
  3. Отформатируйте метку времени с новым часовым поясом (formatter.setTimeZone (...)))
  4. Вернуть строку с новым временем часового пояса. (formatter.format (calendar.getTime ()))

Заранее благодарим за любую помощь: D

Travega
источник
Слишком много вопросов в одном посте ...
Бармалей
Заданы те же 2 вопроса, только второй задается второй раз с алгоритмом сценария для ясности. Спасибо за ввод:?
Travega
Похоже, единственная проблема в том, что 1317816735000Lэто неправильная метка времени 2011-10-06 03:35:05 GMT. В остальном ваш подход правильный.
augurar
1
К вашему сведению, неприятные старые классы даты и времени, такие как java.util.Date, java.util.Calendarи java.text.SimpleDateFormat, теперь унаследованы , вытеснены классами java.time, встроенными в Java 8 и новее. См. Учебник Oracle .
Basil Bourque

Ответы:

62

Для меня самый простой способ сделать это:

Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

//Here you say to java the initial timezone. This is the secret
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
//Will print in UTC
System.out.println(sdf.format(calendar.getTime()));    

//Here you set to your timezone
sdf.setTimeZone(TimeZone.getDefault());
//Will print on your default Timezone
System.out.println(sdf.format(calendar.getTime()));
Чарльстон
источник
1
@Charleston Что reviewв очереди?date = sdf.parse(review);
09Q71AO534
1
@Charleston Но в SDF нет такого типа метода, sdf.parse(DateObject)он не определен в java, который я использую JDK.1.7.
09Q71AO534
Мне очень жаль мой второй ответ. Я даже не тестировал! Но теперь он протестирован и работает!
Чарльстон,
1
Как получить настоящую дату вместо строки?
Tulains Córdova
1
Может быть, это должно быть: SimpleDateFormat ("yyyy-MM-dd hh: mm: ss")
Маркос,
31

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

В любом случае я отвлекся !! Если у вас есть смещение UTC (лучше работать в UTC, чем смещение по Гринвичу), вы можете рассчитать время в миллисекундах и добавить его к своей временной метке. Обратите внимание, что отметка времени SQL может отличаться от отметки времени Java, поскольку способ вычисления времени, прошедшего с эпохи, не всегда одинаков - это зависит от технологий баз данных, а также от операционных систем.

Я бы посоветовал вам использовать System.currentTimeMillis () в качестве меток времени, поскольку они могут обрабатываться более последовательно в java, не беспокоясь о преобразовании меток времени SQL в объекты даты Java и т. Д.

Чтобы рассчитать смещение, вы можете попробовать что-то вроде этого:

Long gmtTime =1317951113613L; // 2.32pm NZDT
Long timezoneAlteredTime = 0L;

if (offset != 0L) {
    int multiplier = (offset*60)*(60*1000);
    timezoneAlteredTime = gmtTime + multiplier;
} else {
    timezoneAlteredTime = gmtTime;
}

Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(timezoneAlteredTime);

DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");

formatter.setCalendar(calendar);
formatter.setTimeZone(TimeZone.getTimeZone(timeZone));

String newZealandTime = formatter.format(calendar.getTime());

Надеюсь, это поможет!

Мукул Гоэль
источник
@ user726478 Это правильно, если мы знаем строку часового пояса? long timezoneAlteredTime = gmtTime + TimeZone.getTimeZone ("Asia / Calcutta"). getRawOffset (); "
Канагавелу Сугумар
4
Не хорошо. Смещение часового пояса не является постоянным. Это зависит от фактической даты.
Дмитрий Трифонов
1
Как получить настоящую дату вместо строки?
Tulains Córdova
@KanagaveluSugumar здесь смещение часов
MY
25

Как всегда, я рекомендую прочитать эту статью о дате и времени в Java, чтобы вы ее поняли.

Основная идея заключается в том, что «под капотом» все делается в миллисекундах UTC с начала эпохи. Это означает, что проще всего работать без использования часовых поясов, за исключением форматирования строки для пользователя.

Поэтому я бы пропустил большинство предложенных вами шагов.

  1. Установите время на объекте (Дата, Календарь и т. Д.).
  2. Установите часовой пояс для объекта форматирования.
  3. Вернуть строку из форматера.

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

Несущий128
источник
Привет, Bringer128, спасибо за ваш ответ. Мне просто кажется смешным, что нет прямого способа настроить временную метку для данного часового пояса. Зачем включать эту функциональность, если все, что она делает, это изменяет тег часового пояса в форматированной строке ... Я попробую Joda time. Спасибо
travega
@travega Есть простой способ, если вы представите свое время как UTC и отформатируете его с помощью SimpleDateFormat. Изменяется не только часть Z (тег часового пояса), но и вся дата. Проверьте результаты установки двух разных объектов SimpleDateFormat с разными часовыми поясами при форматировании одной и той же даты.
Bringer128
Как получить настоящую дату вместо строки?
Tulains Córdova
@ TulainsCórdova Я думаю, вам нужно будет объяснить более подробно. Можете ли вы создать вопрос или выполнить поиск, чтобы найти связанный вопрос, который может решить ваш конкретный вопрос?
Bringer128
19

tl; dr

Instant.ofEpochMilli( 1_317_816_735_000L )
    .atZone( ZoneId.of( "Pacific/Auckland" ) )
    .format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) )

…также…

LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) )
    .atZone( ZoneId.of( "Pacific/Auckland" ) )

java.time

Вопрос и большинство ответов используют устаревшие устаревшие классы даты и времени из самых ранних версий Java. Эти старые классы оказались хлопотными и запутанными. Избежать их. Вместо этого используйте классы java.time.

ISO 8601

Ваша входная строка почти в стандартном формате ISO 8601. Просто замените ПРОБЕЛ посередине на T.

String input = "2011-10-06 03:35:05".replace( " " , "T" );

LocalDateTime

Теперь выполните синтаксический анализ как a, LocalDateTimeпотому что во входных данных отсутствует информация о смещении от UTC или часовом поясе. A LocalDateTimeне имеет понятия смещения или часового пояса, поэтому он не представляет фактический момент на временной шкале.

LocalDateTime ldt = LocalDateTime.parse( input );

ZoneOffset

Похоже, вы говорите, что из бизнес-контекста вы знаете, что цель этой строки - представить момент, который на 13 часов опережает UTC. Итак, мы создаем экземпляр ZoneOffset.

ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.

OffsetDateTime

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

OffsetDateTime odt = ldt.atOffset( offset);

ZoneId

Но затем вы упомянули Новую Зеландию. Итак, вы имели в виду конкретный часовой пояс. Часовой пояс - это смещение от UTC плюс набор правил для обработки аномалий, таких как переход на летнее время (DST). Таким образом , мы можем указать ZoneIdк , ZonedDateTimeа не просто смещение.

Укажите правильное имя часового пояса . Никогда не используйте аббревиатуру из 3-4 букв, например ESTили, ISTпоскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!). Например, Pacific/Auckland.

ZoneId z = ZoneId.of( "Pacific/Auckland" );

ZonedDateTime

Примените ZoneId.

ZonedDateTime zdt = ldt.atZone( z );

Вы можете легко перейти в другую зону в тот же момент на временной шкале.

ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis );  // Same moment in time, but seen through lens of Paris wall-clock time.

Отсчитывать от эпохи

Я настоятельно рекомендую не обрабатывать значения даты и времени как отсчет от эпохи, например миллисекунды с начала 1970 года по Гринвичу. Но если нужно, создайте Instantиз такого числа.

Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );

Затем при желании назначьте часовой пояс, как показано выше, чтобы отойти от UTC.

ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = instant.atZone( z );

Ваша ценность 1_317_816_735_000L:

  • 2011-10-05T12:12:15Z (Среда, 5 октября 2011 г., 12:12:15 GMT)
  • 2011-10-06T01:12:15+13:00[Pacific/Auckland] (Четверг, 6 октября 2011 г., 01:12:15 в Окленде, Новая Зеландия).

Генерация строк

Чтобы сгенерировать строку в стандартном формате ISO 8601 , просто вызовите toString. Обратите внимание, что ZonedDateTimeстандартный формат разумно расширяется, добавляя название часового пояса в квадратных скобках.

String output = zdt.toString();

Для других форматов ищите Stack Overflow для DateTimeFormatterкласса. Уже много раз освещали.

Укажите a FormatStyleи a Locale.

Locale l = new Locale( "en" , "NZ" );
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
String output = zdt.format( f );

Обратите внимание, что часовой пояс не имеет ничего общего с локалью. Вы можете Europe/Parisотображать дату и время на японском языке и культурных нормах или Asia/Kolkataдату и время на португальском языке и культурных нормах Бразилии.

О java.time

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

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

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

Большая часть функциональных возможностей java.time перенесена на Java 6 и 7 в ThreeTen-Backport и дополнительно адаптирована для Android в ThreeTenABP (см. Как использовать… ).

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

Василий Бурк
источник
10

Решение на самом деле довольно простое (чистая, простая Java):

System.out.println(" NZ Local Time: 2011-10-06 03:35:05");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localNZ = LocalDateTime.parse("2011-10-06 03:35:05",formatter);
ZonedDateTime zonedNZ = ZonedDateTime.of(localNZ,ZoneId.of("+13:00"));
LocalDateTime localUTC = zonedNZ.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
System.out.println("UTC Local Time: "+localUTC.format(formatter));

ВЫХОД:

 NZ Local Time: 2011-10-06 03:35:05
UTC Local Time: 2011-10-05 14:35:05
JS Raggio
источник
1
Это было решено 4 года назад, и ваше решение не добавляет ничего нового.
travega
1
Я думаю, что это новый подход с использованием Java 8, но качество ответов низкое.
Przemek
6

Посмотрел, и я не думаю, что в Java есть часовой пояс, который равен GMT + 13. Так что я думаю, вам нужно использовать:

Calendar calendar = Calendar.getInstance();
//OR Calendar.getInstance(TimeZone.getTimeZone("GMT"));

calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY)+13);

Date d = calendar.getTime();

(Если есть, измените "GMT" на этот часовой пояс и удалите вторую строку кода)

ИЛИ ЖЕ

SimpleDateFormat df = new SimpleDateFormat();
df.setTimeZone(TimeZone.getTimeZone("GMT+13"));
System.out.println(df.format(c.getTime()));

Если вы хотите установить определенное время / дату, вы также можете использовать:

    calendar.set(Calendar.DATE, 15);
calendar.set(Calendar.MONTH, 3);
calendar.set(Calendar.YEAR, 2011);
calendar.set(Calendar.HOUR_OF_DAY, 13); 
calendar.set(Calendar.MINUTE, 45);
calendar.set(Calendar.SECOND, 00);

источник
1
Привет, Крейг, спасибо за ответ. Java не поддерживает / не поддерживает стандарты времени ISO. GMT - это глобальный стандарт времени, модерируемый независимо от java. Время / календарь Apis придерживаются стандарта, а GMT + 13 относится к NZDT или летнему времени в любой зоне GMT ​​+ 12. Что касается вашего примера кода, у меня ваш сценарий работает без каких-либо проблем, как указано в моем IP. Проблема, с которой я столкнулся, заключается в определении метки времени и выводе точных вариантов исходной метки времени для конкретных часовых поясов, а НЕ производных от текущего времени, что и делает ваш код. Спасибо T
travega
3

Мы можем справиться с этим, используя значение смещения

 public static long convertDateTimeZone(long lngDate, String fromTimeZone,
        String toTimeZone){
    TimeZone toTZ = TimeZone.getTimeZone(toTimeZone);
    Calendar toCal = Calendar.getInstance(toTZ);        

    TimeZone fromTZ = TimeZone.getTimeZone(fromTimeZone);
    Calendar fromCal = Calendar.getInstance(fromTZ);
    fromCal.setTimeInMillis(lngDate);
    toCal.setTimeInMillis(fromCal.getTimeInMillis()
            + toTZ.getOffset(fromCal.getTimeInMillis())
            - TimeZone.getDefault().getOffset(fromCal.getTimeInMillis()));      
    return toCal.getTimeInMillis();
}

Фрагмент тестового кода:

 System.out.println(new Date().getTime())
 System.out.println(convertDateTimeZone(new Date().getTime(), TimeZone
                .getDefault().getID(), "EST"));

Выход: 1387353270742 1387335270742

DeepaGanesh
источник
2

Я пробовал этот код

try{
            SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss Z");
            Date datetime = new Date();

            System.out.println("date "+sdf.format(datetime));

            sdf.setTimeZone(TimeZone.getTimeZone("GMT"));

            System.out.println("GMT "+ sdf.format(datetime));

            sdf.setTimeZone(TimeZone.getTimeZone("GMT+13"));

            System.out.println("GMT+13 "+ sdf.format(datetime));

            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

            System.out.println("utc "+sdf.format(datetime));

            Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

            DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");    
            formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));  

            String newZealandTime = formatter.format(calendar.getTime());

            System.out.println("using calendar "+newZealandTime);

        }catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

и получив этот результат

date 06-10-2011 10:40:05 +0530
GMT 06-10-2011 05:10:05 +0000 // here getting 5:10:05
GMT+13 06-10-2011 06:10:05 +1300 // here getting 6:10:05
utc 06-10-2011 05:10:05 +0000
using calendar 06 Oct 2011 18:10:05 GMT+13:00
Pratik
источник
Привет, pratik, спасибо за ваш вклад, но вы упускаете суть. Как упоминалось в моем IP-адресе, он работает с текущей меткой времени. Проблема заключается в установке метки времени и последующем создании точных выходных данных для конкретного часового пояса.
Travega
да, это тоже сработает, если вы измените время. Часовой пояс был установлен в объекте форматирования, поэтому любое время, которое вы передали, будет основано на часовом поясе, который был указан в объекте форматирования
Pratik
Хмммм ... Я пробовал добавить: datetime.setTime (Timestamp.valueOf ("2011-10-06 03:35:05"). GetTime ()); И все равно не работает. Как вы понимаете, как это работает, когда вы устанавливаете время?
Travega
@Pratik: Как мне узнать часовой пояс AST.
Ved Prakash
2

Джода-Тайм

Классы java.util.Date/Calendar - беспорядок, и их следует избегать.

Обновление: проект Joda-Time находится в режиме обслуживания. Команда советует перейти на классы java.time.

Вот ваш ответ с использованием библиотеки Joda-Time 2.3. Очень просто.

Как отмечено в примере кода, я предлагаю вам по возможности использовать именованные часовые пояса, чтобы ваша программа могла обрабатывать летнее время (DST) и другие аномалии.

Если вы поместили Tв середину строки вместо пробела, вы можете пропустить первые две строки кода, имея дело с программой форматирования для синтаксического анализа строки. Конструктор DateTime может принимать строку в формате ISO 8601 .

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;

// Parse string as a date-time in UTC (no time zone offset).
DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern( "yyyy-MM-dd' 'HH:mm:ss" );
DateTime dateTimeInUTC = formatter.withZoneUTC().parseDateTime( "2011-10-06 03:35:05" );

// Adjust for 13 hour offset from UTC/GMT.
DateTimeZone offsetThirteen = DateTimeZone.forOffsetHours( 13 );
DateTime thirteenDateTime = dateTimeInUTC.toDateTime( offsetThirteen );

// Hard-coded offsets should be avoided. Better to use a desired time zone for handling Daylight Saving Time (DST) and other anomalies.
// Time Zone list… http://joda-time.sourceforge.net/timezones.html
DateTimeZone timeZoneTongatapu = DateTimeZone.forID( "Pacific/Tongatapu" );
DateTime tongatapuDateTime = dateTimeInUTC.toDateTime( timeZoneTongatapu );

Сбросьте эти значения…

System.out.println( "dateTimeInUTC: " + dateTimeInUTC );
System.out.println( "thirteenDateTime: " + thirteenDateTime );
System.out.println( "tongatapuDateTime: " + tongatapuDateTime );

При запуске…

dateTimeInUTC: 2011-10-06T03:35:05.000Z
thirteenDateTime: 2011-10-06T16:35:05.000+13:00
tongatapuDateTime: 2011-10-06T16:35:05.000+13:00
Василий Бурк
источник
2

отображать дату и время для всех часовых поясов

import java.util.Calendar;
import java.util.TimeZone;
import java.text.DateFormat;
import java.text.SimpleDateFormat;



static final String ISO8601 = "yyyy-MM-dd'T'HH:mm:ssZ";
DateFormat dateFormat = new SimpleDateFormat(ISO8601);
Calendar c = Calendar.getInstance();
String formattedTime;
for (String availableID : TimeZone.getAvailableIDs()) {
    dateFormat.setTimeZone(TimeZone.getTimeZone(availableID));
    formattedTime = dateFormat.format(c.getTime());
    System.out.println(formattedTime + " " + availableID);
}
Кшиштоф Дзюба
источник
1

Мы можем получить отметку времени UTC / GMT от заданной даты.

/**
 * Get the time stamp in GMT/UTC by passing the valid time (dd-MM-yyyy HH:mm:ss)
 */
public static long getGMTTimeStampFromDate(String datetime) {
    long timeStamp = 0;
    Date localTime = new Date();

    String format = "dd-MM-yyyy HH:mm:ss";
    SimpleDateFormat sdfLocalFormat = new SimpleDateFormat(format);
    sdfLocalFormat.setTimeZone(TimeZone.getDefault());

    try {

        localTime = (Date) sdfLocalFormat.parse(datetime); 

        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"),
                Locale.getDefault());
        TimeZone tz = cal.getTimeZone();

        cal.setTime(localTime);

        timeStamp = (localTime.getTime()/1000);
        Log.d("GMT TimeStamp: ", " Date TimegmtTime: " + datetime
                + ", GMT TimeStamp : " + localTime.getTime());

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return timeStamp;

}

Он вернет время в формате UTC на основе прошедшей даты.

  • Мы можем сделать обратное, например отметку времени UTC, на текущую дату и время (наоборот)

        public static String getLocalTimeFromGMT(long gmtTimeStamp) {
                 try{
                        Calendar calendar = Calendar.getInstance();
                        TimeZone tz = TimeZone.getDefault();
                        calendar.setTimeInMillis(gmtTimeStamp * 1000);
        //              calendar.add(Calendar.MILLISECOND, tz.getOffset(calendar.getTimeInMillis())); 
                        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
                        Date currenTimeZone = (Date) calendar.getTime();
                        return sdf.format(currenTimeZone);
                    }catch (Exception e) {
                    }
                    return "";  
                }
    

Надеюсь, это поможет другим. Благодаря!!

Джагдиш
источник
1

Быстрый способ:

String dateText ="Thu, 02 Jul 2015 21:51:46";
long hours = -5; // time difference between places

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(E, dd MMM yyyy HH:mm:ss, Locale.ENGLISH);     
LocalDateTime date = LocalDateTime.parse(dateText, formatter);        
date = date.with(date.plusHours(hours));

System.out.println("NEW DATE: "+date);

Вывод

НОВАЯ ДАТА: 2015-07-02T16: 51: 46

Ev.
источник
1

Ваш подход работает без каких-либо изменений.

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// Timestamp for 2011-10-06 03:35:05 GMT
calendar.setTime(new Date(1317872105000L));

DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); 
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));

// Prints 2011-10-06 16:35:05 GMT+13:00
System.out.println(formatter.format(calendar.getTime()));
авгурар
источник
1
public Timestamp convertLocalTimeToServerDatetime(String dt,String timezone){

    String clientDnT = dt ;// "2017-06-01 07:20:00";
    try{
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date = sdf.parse(clientDnT);
    TimeZone tz = TimeZone.getTimeZone(timezone.trim()); // get time zone of user
    sdf.setTimeZone(tz);

    // Convert to servertime zone 
    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    TimeZone tzInAmerica = TimeZone.getDefault();
    sdf1.setTimeZone(tzInAmerica);

    // assign date to date
    String serverDate = sdf1.format(date);

    // Convert to servertime zone to Timestamp
    Date date2 =  sdf.parse(serverDate);
    Timestamp tsm = new Timestamp(date2.getTime());
    return  tsm;
    }
    catch(Exception e){
        System.err.println(e);
    }

    return null;
}
Сурав Бармен
источник
пожалуйста, передайте дату и часовой пояс клиента , тогда метод вернет отметку времени сервера .. для javascript var _timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; и в java TimeZone tz = TimeZone.getDefault(); tz.getID()
Сурав Барман
1

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

import org.joda.time.{DateTime, Period, PeriodType}

val s1 = "2019-06-13T05:50:00-07:00"
val s2 = "2019-10-09T11:30:00+09:00"    

val period = new Period(DateTime.parse(s1), DateTime.parse(s2), PeriodType dayTime())

period.getDays
period.getMinutes
period.getHours

период вывода = P117DT13H40M

days = 117
minutes = 40
hours = 13
Абхишек Сингха
источник
1

Я хотел бы дать современный ответ.

На самом деле вам не нужно преобразовывать дату и время из строки с одним смещением GMT в строку с другим смещением GMT и в другом формате. Скорее в вашей программе сохраняйте момент (момент времени) как надлежащий объект даты и времени. Только когда вам нужно предоставить строковый вывод, отформатируйте ваш объект в желаемую строку.

java.time

Разбор ввода

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral(' ')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .toFormatter();

    String dateTimeString = "2011-10-06 03:35:05";
    Instant instant = LocalDateTime.parse(dateTimeString, formatter)
            .atOffset(ZoneOffset.UTC)
            .toInstant();

Для большинства целей Instantэто хороший выбор для хранения момента времени. Если вам нужно явно указать, что дата и время взяты из GMT, используйте OffsetDateTimeвместо этого.

Преобразование, форматирование и печать вывода

    ZoneId desiredZone = ZoneId.of("Pacific/Auckland");
    Locale desiredeLocale = Locale.forLanguageTag("en-NZ");
    DateTimeFormatter desiredFormatter = DateTimeFormatter.ofPattern(
            "dd MMM uuuu HH:mm:ss OOOO", desiredeLocale);

    ZonedDateTime desiredDateTime = instant.atZone(desiredZone);
    String result = desiredDateTime.format(desiredFormatter);
    System.out.println(result);

Это напечатано:

06 окт 2011 16:35:05 GMT + 13: 00

Я указал часовой пояс Pacific / Auckland, а не указанное вами смещение, +13: 00. Я понял, что вам нужно новозеландское время, и Пасифик / Окленд лучше говорят об этом. Часовой пояс также учитывает летнее время (DST), поэтому вам не нужно учитывать это в вашем собственном коде (для большинства целей).

Поскольку Octон на английском языке, рекомендуется указать форматеру явную локаль. GMTтоже может быть локализован, но я думаю, что он просто печатается GMTво всех регионах.

OOOOв строке шаблонов формата - это один из способов печати смещения, который может быть лучшей идеей, чем печать аббревиатуры часового пояса, которую вы бы получили, zпоскольку сокращения часовых поясов часто неоднозначны. Если хотите NZDT(для летнего времени Новой Зеландии), просто введите zвместо этого.

Ваши вопросы

Я отвечу на ваши пронумерованные вопросы относительно современных классов в java.time.

Возможно:

  1. Установите время на объекте

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

  1. (Возможно) Установите часовой пояс начальной отметки времени

atZoneМетод , который я использую в коде возвращает ZonedDateTimeс заданной временной зоной. Другие классы даты и времени имеют аналогичный метод, иногда называемый atZoneSameInstantили другими именами.

  1. Отформатируйте метку времени с новым часовым поясом

С java.time преобразование в новый часовой пояс и форматирование - это два различных шага, как показано.

  1. Вернуть строку с новым временем часового пояса.

Да, преобразовать в нужный часовой пояс, как показано, и отформатировать, как показано.

Я обнаружил, что каждый раз, когда я пытаюсь установить время следующим образом:

calendar.setTime(new Date(1317816735000L));

используется часовой пояс локального компьютера. Это почему?

Это не так, как вы думаете, что хорошо демонстрирует лишь пару (многих) проблем проектирования со старыми классами.

  • У A Dateнет часового пояса. Только когда вы его распечатываете, его toStringметод захватывает ваш местный часовой пояс и использует его для рендеринга строки. Это верно и для new Date(). Такое поведение смутило многих, многих программистов за последние 25 лет.
  • У A Calender есть часовой пояс. Это не меняется, когда вы это делаете calendar.setTime(new Date(1317816735000L));.

Ссылка

Учебник Oracle: Date Time, объясняющий, как использовать java.time.

Оле В.В.
источник