[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
) - 시간 영역과 (
ZonedDateTime
와ZoneId
)
Instant
에서 java.time , 기본 빌딩 블록은 Instant
UTC의 타임 라인에 순간. 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.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 클래스는 어디서 구할 수 있습니까?
- Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 이상 -번들로 구현 된 표준 Java API의 일부입니다.
- Java 9에는 몇 가지 사소한 기능과 수정 사항이 추가되었습니다.
- Java SE 6 및 Java SE 7
- 대부분의 java.time 기능은 ThreeTen-Backport의 Java 6 & 7로 백 포트됩니다 .
- 기계적 인조 인간
- java.time 클래스 의 최신 버전의 Android 번들 구현 .
- 이전 Android (<26)의 경우 ThreeTenABP 프로젝트 는 위에서 언급 한 ThreeTen-Backport를 채택합니다 . ThreeTenABP 사용 방법…을 참조하십시오 .
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.Calendar
JDK 클래스 만 사용하여 표준 시간대를 처리하는 일반적인 방법입니다. 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);