2008-09-17 4 views
8

У меня есть поле базы данных, которая содержит необработанное поле даты (хранятся в виде символьных данных), например,Лучший способ извлечь объект TimeZone из строки?

Пятницы, 26 Сентября 2008 8:30 вечер по восточному поясному времени

Я могу разобрать это как дата легко, с SimpleDateFormat

DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz"); 
Date scheduledDate = dbFormatter.parse(rawDate); 

То, что я хотел бы сделать, это извлечь объект TimeZone из этой строки. По умолчанию TimeZone в JVM, в котором работает это приложение, - GMT, поэтому я не могу использовать .getTimezoneOffset() из приведенного выше Date (потому что он вернет TimeZone по умолчанию).

Кроме того, чтобы вырезать необработанную строку и найти начальную позицию строки Timezone (так как я знаю, что формат всегда будет EEEE, MMMM dd, yyyy hh:mm aa zzzz), есть способ использования API DateFormat/SimpleDateFormat/Date/Calendar для извлечения объекта TimeZone - который будет иметь тот же TimeZone, что и строка, которую я разобрал в DateFormat.parse()?

Одна вещь, которая мне ошибок о Date против Calendar в Java API, что Calendar предполагается заменить Date во всех местах ... но потом они решили, эй давайте все-таки использовать Date «S в DateFormat классов.

+0

У вас было решение по этой проблеме? – Chin2 2015-09-24 10:54:43

+0

Что касается последнего абзаца, классы «Дата» и «Календарь» - это кровавый беспорядок: плохо спроектированный, запутанный и хлопотный. Избежать их. Вместо этого используйте классы [java.time] (http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html). – 2016-10-26 05:09:13

ответ

0

Ну, как частичное решение, вы можете использовать матч RegEx, чтобы получить часовой пояс, так как перед ним всегда будет один и тот же текст. До или после полудня.

Я не знаю достаточно о часовых поясах Java, чтобы получить последнюю часть.

2

Я обнаружил, что следующее:

 DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz"); 
     dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago")); 
     Date scheduledDate = dbFormatter.parse("Friday, September 26, 2008 8:30 PM Eastern Daylight Time"); 
     System.out.println(scheduledDate); 
     System.out.println(dbFormatter.format(scheduledDate)); 
     TimeZone tz = dbFormatter.getTimeZone(); 
     System.out.println(tz.getDisplayName()); 
     dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago")); 
     System.out.println(dbFormatter.format(scheduledDate)); 

Производит следующее:

Fri Sep 26 20:30:00 CDT 2008 
Friday, September 26, 2008 08:30 PM Eastern Standard Time 
Eastern Standard Time 
Friday, September 26, 2008 08:30 PM Central Daylight Time 

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

Редактировать: Вышеупомянутый был запущен с JDK 1.6 от Sun.

+0

Я был также удивлен этим и столкнулся с проблемами, связанными с TimeZone, скользящими из-за экземпляра Date раньше. – 18Rabbit 2008-09-17 18:37:53

+0

Просто интересно - каков результат TimeZone.getDefault() на вашей машине? – 2008-09-17 18:38:15

0

Основное отличие между датой и календарем заключается в том, что Date является всего лишь объектом значения без методов его модификации. Поэтому он предназначен для хранения информации о дате/времени где-то. Если вы используете объект «Календарь», вы можете изменить его после того, как он настроен на постоянный объект, который выполняет некоторую бизнес-логику с информацией о дате/времени. Это очень опасно, потому что у субъекта нет способа распознать это изменение. Класс Calendar предназначен для операций с датой/временем, например, добавления дней или чего-то в этом роде.

Игра вокруг с вашим примером я получаю следующее:

import java.text.DateFormat; 
import java.text.ParseException; 
import java.text.SimpleDateFormat; 

public class TimeZoneExtracter { 

    public static final void main(String[] args) throws ParseException { 
     DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz"); 
     System.out.println(dbFormatter.getTimeZone()); 
     dbFormatter.parse("Fr, September 26, 2008 8:30 PM Eastern Daylight Time"); 
     System.out.println(dbFormatter.getTimeZone()); 
    } 

} 

Выход:

sun.util.calendar.ZoneInfo [ID = "Europe/Berlin" ... солнца. util.calendar.ZoneInfo [ID = "Африка/Addis_Ababa" ...

Это результат, который вы хотели?

1

@Ed Томас:

Я пытался что-то очень похожий на ваш, например, и я получаю очень разные результаты:

String testString = "Friday, September 26, 2008 8:30 PM Pacific Standard Time"; 
DateFormat df = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz"); 

System.out.println("The default TimeZone is: " + TimeZone.getDefault().getDisplayName()); 

System.out.println("DateFormat timezone before parse: " + df.getTimeZone().getDisplayName()); 

Date date = df.parse(testString); 

System.out.println("Parsed [" + testString + "] to Date: " + date); 

System.out.println("DateFormat timezone after parse: " + df.getTimeZone().getDisplayName()); 

Выход:

по умолчанию TimeZone является: Eastern Стандартное время

DateFormat часовой пояс перед разоблачением: Восточное стандартное время

Parsed [Пятнице, 26 сентября 2008 8:30 вечера по стандартному тихоокеанскому времени] Дата съемки: Сб 27 сентября 00:30:00 EDT 2008

DateFormat часовой пояс после синтаксического анализа: Eastern Standard Time

Кажется, что DateFormat.getTimeZone() возвращает тот же TimeZone до и после parse() ... даже если я нахожу явно setTimeZone() перед вызовом parse().

Рассматривая источник DateFormat и SimpleDateFormat, кажется, что getTimeZone() просто возвращает TimeZone базового Календаря ... который по умолчанию будет использовать календарь Locale/TimeZone по умолчанию, если вы не укажете какой-либо один из них.

0

Эд имеет право. вы хотите, чтобы timeZone на объекте DateFormat после того, как время было проанализировано.

String rawDate = "Friday, September 26, 2008 8:30 PM Eastern Daylight Time"; 
DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz"); 
Date scheduledDate = dbFormatter.parse(rawDate); 

System.out.println(rawDate); 
System.out.println(scheduledDate); 
System.out.println(dbFormatter.getTimeZone().getDisplayName()); 

производит

Friday, September 26, 2008 8:30 PM Eastern Daylight Time 
Fri Sep 26 20:30:00 CDT 2008 
Eastern Standard Time 
1

Я рекомендую проверить на даты и времени Joda Time API. Недавно я был обращен к верующему, поскольку он, как правило, превосходит встроенную поддержку дат и времени на Java. В частности, вы должны проверить класс DateTimeZone. Надеюсь это поможет.

http://joda-time.sourceforge.net/

http://joda-time.sourceforge.net/api-release/index.html

0

Т.Л., д-р

ZonedDateTime.parse( 
    "Friday, September 26, 2008 8:30 PM Eastern Daylight Time" , 
    DateTimeFormatter.ofPattern("EEEE, MMMM d, uuuu h:m a zzzz") 
).getZone() 

java.time

Современный путь с классами java.time. Вопросы и другие ответы используют неприятные старые устаревшие классы времени или проект Joda-Time, оба из которых теперь вытесняются классами java.time.

Определить объект DateTimeFormatter с шаблоном форматирования в соответствии с вашими данными.

DateTimeFormatter f = DateTimeFormatter.ofPattern("EEEE, MMMM d, uuuu h:m a zzzz"); 

Назначить Locale указать человеческий язык дня имя-и название месяца, а также культурные нормы для других вопросов форматирования.

f = f.withLocale(Locale.US); 

Наконец, сделать синтаксический анализ, чтобы получить ZonedDateTime объект.

String input = "Friday, September 26, 2008 8:30 PM Eastern Daylight Time" ; 
ZonedDateTime zdt = ZonedDateTime.parse(input , f); 

zdt.toString(): 2008-09-26T20: 30-04: 00 [Америка/New_York]

Вы можете задать для часового пояса от ZonedDateTime, представленного в a ZoneId объект. Затем вы можете допросить ZoneId, если вам нужна дополнительная информация о часовом поясе.

ZoneId z = zdt.getZone(); 

See for yourself in IdeOne.com.

ISO 8601

Избегайте обмен данных даты и время в этом виде ужасного формата. Не принимайте на себя английский язык, не делайте аксессуар своей продукции с такими вещами, как имя дня, и никогда не используйте псевдо-часовые зоны, такие как Eastern Daylight Time.

Для часовых поясов: Указать proper time zone name в формате continent/region, такие как America/Montreal, Africa/Casablanca или Pacific/Auckland. Никогда не используйте аббревиатуру 3-4 буквы, такую ​​как EST или IST, поскольку они не являются настоящими часовыми поясами, а не стандартизированы и даже не уникальны (!).

Для сериализации значений даты и времени для текста используйте только форматы ISO 8601. Классы java.time используют эти форматы по умолчанию при разборе/генерации строк для представления их значения.


О java.time

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

Проект Joda-Time, теперь в maintenance mode, советует перейти на java.time.

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

Где получить классы java.time?

  • Java SE 8 и SE 9, а затем
    • Встроенный.
    • Часть стандартного Java API с объединенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и SE 7
    • Большая часть функциональности java.time будет обратно портирован на Java 6 & 7 в ThreeTen-Backport.
  • Android
    • Проект ThreeTenABP адаптирует ThreeTen-Backport (как упоминалось выше) для Android специально.
    • См. How to use….

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

 Смежные вопросы

  • Нет связанных вопросов^_^