[java] java.util.Date의 시간대를 설정하는 방법은 무엇입니까?

java.util.Date에서를 파싱 String했지만 로컬 시간대를 date객체 의 시간대로 설정하고 있습니다.

구문 분석 String할 표준 시간대가 지정되지 않았습니다 Date. date개체 의 특정 시간대를 설정하고 싶습니다 .

어떻게해야합니까?



답변

DateFormat을 사용하십시오. 예를 들어

SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = isoFormat.parse("2010-05-23T09:01:02");


답변

주의하십시오 java.util.Date물체가 그 자체로 어떤 시간대 정보를 포함하지 않는다 – 당신이에 시간대를 설정할 수 없습니다 Date객체입니다. Date개체에 포함 된 유일한 것은 “epoch”이후 1970 년 1 월 1 일 00:00:00 UTC 이후의 밀리 초입니다.

ZZ 코더가 보여 주듯이, DateFormat날짜와 시간을 표시 할 시간대를 알려주기 위해 객체 의 시간대를 설정합니다 .


답변

tl; dr

… 문자열에서 파싱… 시간대가 지정되지 않았습니다… 특정 시간대를 설정하고 싶습니다

LocalDateTime.parse( "2018-01-23T01:23:45.123456789" )  // Parse string, lacking an offset-from-UTC and lacking a time zone, as a `LocalDateTime`.
    .atZone( ZoneId.of( "Africa/Tunis" ) )              // Assign the time zone for which you are certain this date-time was intended. Instantiates a `ZonedDateTime` object.

juDate에 시간대 없음

다른 정답이 언급했듯이 java.util.Date에는 시간대 이 없습니다 . UTC / GMT (표준 시간대 오프셋 없음)를 나타냅니다 . toString메소드가 문자열 표현을 생성 할 때 JVM의 기본 시간대를 적용 하기 때문에 매우 혼란 스럽습니다 .

사법을 피하십시오

이것과 다른 많은 이유로 인해 내장 java.util.Date & .Calendar & java.text.SimpleDateFormat을 사용하지 않아야합니다. 그들은 악명 높은 문제입니다.

대신 Java 8 과 함께 제공되는 java.time 패키지를 사용하십시오 .

java.time

java.time 클래스는 세 가지 방식으로 타임 라인의 순간을 나타낼 수 있습니다.

  • UTC ( Instant)
  • (오프셋 OffsetDateTime하여 ZoneOffset)
  • 시간 영역과 ( ZonedDateTimeZoneId)

Instant

에서 java.time , 기본 빌딩 블록은 InstantUTC의 타임 라인에 순간. Instant많은 비즈니스 로직에 객체를 사용하십시오 .

Instant instant = Instant.now();

OffsetDateTime

UTC오프셋을 적용하여 일부 지역의 벽시계 시간 을 조정하십시오 .

를 적용 ZoneOffset하려면을 적용하십시오 OffsetDateTime.

ZoneOffset zoneOffset = ZoneOffset.of( "-04:00" );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );

ZonedDateTime

표준 시간대 , 오프셋 일광 절약 시간 (DST) 과 같은 예외 처리 규칙 을 적용하는 것이 좋습니다 .

에 a ZoneId를 적용하여 a 을 Instant얻습니다 ZonedDateTime. 항상 올바른 시간대 이름을 지정하십시오 . 안 등 3 ~ 4 약어를 사용하지 EST또는 IST도 독특한도 표준화됩니다.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

LocalDateTime

입력 문자열에 오프셋 또는 영역 표시기가없는 경우 a로 구문 분석하십시오 LocalDateTime.

원하는 시간대를 확신 할 수있는 경우 a ZoneId를 지정하여을 생성하십시오 ZonedDateTime. 위의 tl; dr 섹션에서 위의 코드 예제를 참조하십시오 .

형식화 된 문자열

toString이 세 클래스 중 하나 에서 메소드를 호출하여 표준 ISO 8601 형식 의 날짜-시간 값을 나타내는 문자열을 생성하십시오 . 이 ZonedDateTime클래스는 표준 시간대 이름을 괄호 안에 추가하여 표준 형식을 확장합니다.

String outputInstant = instant.toString(); // Ex: 2011-12-03T10:15:30Z
String outputOdt = odt.toString(); // Ex: 2007-12-03T10:15:30+01:00
String outputZdt = zdt.toString(); // Ex: 2007-12-03T10:15:30+01:00[Europe/Paris]

다른 형식의 경우 DateTimeFormatter클래스를 사용하십시오 . 일반적으로 해당 클래스가 사용자의 예상되는 언어 및 문화적 규범을 사용하여 현지화 된 형식을 생성하도록하는 것이 가장 좋습니다. 또는 특정 형식을 지정할 수 있습니다.


최신 및 기존 Java의 모든 날짜-시간 유형 표


java.time에 대하여

java.time의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 까다로운 기존에 대신 기존 과 같은 날짜 – 시간의 수업을 java.util.Date, Calendar, SimpleDateFormat.

Joda 타임 프로젝트는 지금에 유지 관리 모드 의로 마이그레이션을 조언 java.time의 클래스.

자세한 내용은 Oracle Tutorial을 참조하십시오 . 많은 예제와 설명을 보려면 스택 오버플로를 검색하십시오. 사양은 JSR 310 입니다.

java.time 객체를 데이터베이스와 직접 교환 할 수 있습니다 . JDBC 4.2 이상을 준수 하는 JDBC 드라이버를 사용하십시오 . 문자열이 필요없고 수업이 필요 없습니다 .java.sql.*

java.time 클래스는 어디서 구할 수 있습니까?

ThreeTen – 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 향후 java.time에 추가 될 수있는 입증 된 근거입니다. 당신은 여기에 몇 가지 유용한 클래스와 같은 찾을 수 있습니다 Interval, YearWeek, YearQuarter, 그리고 .


조다 타임

하지만 Joda 타임은 여전히 활발하게 유지되고, 그 업체는 빨리 편리으로 java.time로 마이그레이션라고 우리에게 이야기했다. 이 섹션은 참조로 그대로두고 java.time위 의 섹션을 대신 사용하는 것이 좋습니다 .

Joda-시간 , 날짜 – 시간 객체 ( DateTime) 진정으로 할당 된 시간대를 알 수 없습니다. 즉, UTC 해당 표준 시간대의 일광 절약 시간제 (DST) 및 기타 예외의 규칙 및 기록 의 오프셋을 의미합니다 .

String input = "2014-01-02T03:04:05";
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( input, timeZone );
DateTime dateTimeUtcGmt = dateTimeIndia.withZone( DateTimeZone.UTC );

toString메소드를 호출하여 ISO 8601 형식 의 문자열을 생성하십시오 .

String output = dateTimeIndia.toString();

Joda-Time은 또한 모든 종류의 다른 문자열 형식을 생성 할 수있는 다양한 기능을 제공합니다.

필요한 경우 Joda-Time DateTime에서 java.util.Date로 변환 할 수 있습니다.

Java.util.Date date = dateTimeIndia.toDate();

“joda date”에 대한 StackOverflow를 검색하여 더 많은 예를 찾으십시오.


사실이 있다 몇 가지 내부 기능에 사용되는 java.util.Date에 포함 된 시간대가 (이 답변에 대한 의견을 참조). 그러나이 내부 시간대는 속성으로 노출되지 않으므로 설정할 수 없습니다. 이 내부 시간대는 날짜-시간 값의 문자열 표현을 생성하는 방법에서 사용되는 시간대가 아닙니다toString . 대신 JVM의 현재 기본 시간대가 즉시 적용됩니다. 간단히 말해서“juDate에는 시간대가 없습니다”라고 말합니다. 혼란 스러운가? 예. 피곤한 구식 수업을 피해야 할 또 다른 이유.


답변

JVM 레벨에서 시간대를 설정할 수도 있습니다.

Date date1 = new Date();
System.out.println(date1);

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
// or pass in a command line arg: -Duser.timezone="UTC"

Date date2 = new Date();
System.out.println(date2);

산출:

Thu Sep 05 10:11:12 EDT 2013
Thu Sep 05 14:11:12 UTC 2013


답변

표준 JDK 클래스로만 작업해야하는 경우 다음을 사용할 수 있습니다.

/**
 * Converts the given <code>date</code> from the <code>fromTimeZone</code> to the
 * <code>toTimeZone</code>.  Since java.util.Date has does not really store time zome
 * information, this actually converts the date to the date that it would be in the
 * other time zone.
 * @param date
 * @param fromTimeZone
 * @param toTimeZone
 * @return
 */
public static Date convertTimeZone(Date date, TimeZone fromTimeZone, TimeZone toTimeZone)
{
    long fromTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, fromTimeZone);
    long toTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, toTimeZone);

    return new Date(date.getTime() + (toTimeZoneOffset - fromTimeZoneOffset));
}

/**
 * Calculates the offset of the <code>timeZone</code> from UTC, factoring in any
 * additional offset due to the time zone being in daylight savings time as of
 * the given <code>date</code>.
 * @param date
 * @param timeZone
 * @return
 */
private static long getTimeZoneUTCAndDSTOffset(Date date, TimeZone timeZone)
{
    long timeZoneDSTOffset = 0;
    if(timeZone.inDaylightTime(date))
    {
        timeZoneDSTOffset = timeZone.getDSTSavings();
    }

    return timeZone.getRawOffset() + timeZoneDSTOffset;
}

크레딧은이 게시물 로 이동합니다 .


답변

java.util.CalendarJDK 클래스 만 사용하여 표준 시간대를 처리하는 일반적인 방법입니다. Apache Commons 에는 도움이 될만한 다른 대안 / 유틸리티가 있습니다. 편집 스폰지의 메모는 Joda-Time 에 대해 정말 좋은 소식을 들었습니다 (내가 직접 사용하지는 않았지만).


답변

Date를 String으로 변환하고 SimpleDateFormat을 사용하여 수행하십시오.

    SimpleDateFormat readFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    readFormat.setTimeZone(TimeZone.getTimeZone("GMT" + timezoneOffset));
    String dateStr = readFormat.format(date);
    SimpleDateFormat writeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    Date date = writeFormat.parse(dateStr);