답변:
ZonedDateTime을 Date와 직접 사용할 수있는 인스턴트로 변환 할 수 있습니다.
Date.from(java.time.ZonedDateTime.now().toInstant());
Date
는 epoch 이후 밀리 초 수이므로 UTC와 관련이 있습니다. 당신이 경우 인쇄 를 기본 시간대가 사용되지만, Date 클래스에서 ... 참조는 예를 들어 "매핑"섹션은 사용자의 시간대에 대한 지식이없는 docs.oracle.com/javase/tutorial/datetime/iso/legacy을 .html 중에서 ... 혼란으로 볼 수있다 - 그리고 LocalDateTime은 시간대에 관계없이 명시 적이다
ZonedDateTime
. 이 java.time.Instant
클래스는을 직접 대체하며 java.util.Date
둘 다 UTC로 순간을 나타내지 만 Instant
밀리 초 대신 나노초의 더 미세한 해상도를 사용합니다. Date.from( Instant.now() )
당신의 해결책이어야했습니다. 또는 그 문제 new Date()
에 대해 UTC로 현재 순간을 캡처하여 동일한 효과를 발휘합니다.
java.util.Date.from( // Transfer the moment in UTC, truncating any microseconds or nanoseconds to milliseconds.
Instant.now() ; // Capture current moment in UTC, with resolution as fine as nanoseconds.
)
위의 코드에는 의미가 없지만. 모두 java.util.Date
와 Instant
항상 UTC에, UTC의 순간을 나타냅니다. 위의 코드는 다음과 같은 효과가 있습니다.
new java.util.Date() // Capture current moment in UTC.
여기서 ZonedDateTime
. 이미있는 경우 ZonedDateTime
,을 추출하여 UTC로 조정합니다 Instant
.
java.util.Date.from( // Truncates any micros/nanos.
myZonedDateTime.toInstant() // Adjust to UTC. Same moment, same point on the timeline, different wall-clock time.
)
그만큼 응답 하여 ssoltanid은 올바르게 새로운 학교 java.time 객체를 (변환하는 방법, 특정 질문을 해결 ZonedDateTime
오래된 학교에) java.util.Date
객체입니다. Instant
ZonedDateTime에서를 추출하고 java.util.Date.from()
.
이 점에 유의 데이터 손실을 고통 으로, Instant
트랙 나노초 이후 시대 동안 java.util.Date
트랙 (밀리 초) 시대입니다.
귀하의 질문과 의견은 다른 문제를 제기합니다.
일반적으로 서버는 호스트 OS를 UTC로 설정해야합니다. JVM은 내가 알고있는 Java 구현에서이 호스트 OS 설정을 기본 시간대로 선택합니다.
그러나 JVM의 현재 기본 시간대에 의존해서는 안됩니다. 호스트 설정을 선택하는 대신 JVM을 시작할 때 전달 된 플래그가 다른 시간대를 설정할 수 있습니다. 더 나쁜 점은 앱의 모든 스레드에있는 모든 코드가 java.util.TimeZone::setDefault
런타임에 기본값을 변경하도록 호출 할 수 있다는 것입니다.
Timestamp
유형모든 괜찮은 데이터베이스 및 드라이버가 자동으로 저장을 위해 UTC에 전달 된 날짜와 시간을 조정 처리해야합니다. 나는 Cassandra를 사용하지 않지만 날짜 시간에 대한 기본적인 지원이있는 것 같습니다. 문서에 따르면Timestamp
유형은 동일한 시대 (UTC에서 1970 년의 첫 순간)의 밀리 초 수입니다.
또한 Cassandra는 ISO 8601 표준 형식 의 문자열 입력을 허용합니다 . 다행히 java.time은 문자열 구문 분석 / 생성을위한 기본값으로 ISO 8601 형식을 사용합니다. Instant
클래스 'toString
구현은 잘 할 것입니다.
그러나 먼저 ZonedDateTime의 나노초 정밀도를 밀리 초로 줄여야합니다. 한 가지 방법은 밀리 초를 사용하여 새로운 인스턴트를 만드는 것입니다. 다행히 java.time에는 밀리 초 단위로 변환하는 몇 가지 편리한 방법이 있습니다.
다음은 Java 8 업데이트 60의 몇 가지 예제 코드입니다.
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
…
Instant instant = zdt.toInstant();
Instant instantTruncatedToMilliseconds = Instant.ofEpochMilli( instant.toEpochMilli() );
String fodderForCassandra = instantTruncatedToMilliseconds.toString(); // Example: 2015-08-18T06:36:40.321Z
또는이 Cassandra Java 드라이버 문서 에 따라 java.util.Date
인스턴스를 전달할 수 있습니다 (와 혼동하지 마십시오 java.sqlDate
). 따라서 instantTruncatedToMilliseconds
위 코드에서 juDate를 만들 수 있습니다.
java.util.Date dateForCassandra = java.util.Date.from( instantTruncatedToMilliseconds );
이렇게 자주하면 한 줄로 만들 수 있습니다.
java.util.Date dateForCassandra = java.util.Date.from( zdt.toInstant() );
그러나 약간의 유틸리티 방법을 만드는 것이 더 깔끔 할 것입니다.
static public java.util.Date toJavaUtilDateFromZonedDateTime ( ZonedDateTime zdt ) {
Instant instant = zdt.toInstant();
// Data-loss, going from nanosecond resolution to milliseconds.
java.util.Date utilDate = java.util.Date.from( instant ) ;
return utilDate;
}
이 모든 코드가 질문과 다른 점을 주목하십시오. 질문의 코드는 ZonedDateTime 인스턴스의 시간대를 UTC로 조정하려고했습니다. 그러나 그것은 필요하지 않습니다. 개념적으로 :
ZonedDateTime = 인스턴트 + ZoneId
이미 UTC로되어있는 Instant 부분을 추출하기 만하면됩니다 (기본적으로 UTC로되어 있습니다. 정확한 세부 사항은 클래스 문서를 참조하십시오).
java.time의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 까다로운 기존에 대신 기존 과 같은 날짜 - 시간의 수업을 java.util.Date
, Calendar
, SimpleDateFormat
.
Joda 타임 지금 프로젝트, 유지 관리 모드는 의에 마이그레이션을 조언 java.time 클래스.
자세한 내용은 Oracle Tutorial을 참조하십시오 . 그리고 많은 예제와 설명을 위해 Stack Overflow를 검색하십시오. 사양은 JSR 310 입니다.
java.time 객체를 데이터베이스와 직접 교환 할 수 있습니다 . JDBC 4.2 이상을 준수 하는 JDBC 드라이버를 사용하십시오 . 문자열이나 클래스 가 필요하지 않습니다 .java.sql.*
java.time 클래스는 어디서 구할 수 있습니까?
ThreeTen - 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 java.time에 향후 추가 될 수있는 가능성을 입증하는 곳입니다. 당신은 여기에 몇 가지 유용한 클래스와 같은 찾을 수 있습니다 Interval
, YearWeek
, YearQuarter
, 그리고 더 .
다음은 현재 시스템 시간을 UTC로 변환하는 예입니다. ZonedDateTime을 문자열로 형식화 한 다음 문자열 개체는 java.text DateFormat을 사용하여 날짜 개체로 구문 분석됩니다.
ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC);
final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
final DateFormat FORMATTER_YYYYMMDD_HH_MM_SS = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
String dateStr = zdt.format(DATETIME_FORMATTER);
Date utcDate = null;
try {
utcDate = FORMATTER_YYYYMMDD_HH_MM_SS.parse(dateStr);
}catch (ParseException ex){
ex.printStackTrace();
}
Android 용 ThreeTen 백 포트 를 사용 중이고 최신 버전 Date.from(Instant instant)
(최소 API 26 필요)을 사용할 수없는 경우 다음을 사용할 수 있습니다.
ZonedDateTime zdt = ZonedDateTime.now();
Date date = new Date(zdt.toInstant().toEpochMilli());
또는:
Date date = DateTimeUtils.toDate(zdt.toInstant());
Basil Bourque의 답변 에서 조언을 읽어보십시오.
DateTimeUtils
변환 메서드가 있는 클래스가 포함 되어 있으므로 Date date = DateTimeUtils.toDate (zdt.toInstant ());`를 사용합니다. 그렇게 낮은 수준이 아닙니다.
Java 8 이상에 내장 된 java.time 클래스를 사용하여 이를 수행 할 수 있습니다 .
ZonedDateTime temporal = ...
long epochSecond = temporal.getLong(INSTANT_SECONDS);
int nanoOfSecond = temporal.get(NANO_OF_SECOND);
Date date = new Date(epochSecond * 1000 + nanoOfSecond / 1000000);
Instant
s는 초와 나노초를 추적합니다. Date
s 트랙 밀리 초. 이 변환은 하나에서 다른 것으로 올 바릅니다.
나는 이것을 사용한다.
public class TimeTools {
public static Date getTaipeiNowDate() {
Instant now = Instant.now();
ZoneId zoneId = ZoneId.of("Asia/Taipei");
ZonedDateTime dateAndTimeInTai = ZonedDateTime.ofInstant(now, zoneId);
try {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateAndTimeInTai.toString().substring(0, 19).replace("T", " "));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
Date.from(java.time.ZonedDateTime.ofInstant(now, zoneId).toInstant());
작동하지 않기 때문에
!!! 컴퓨터에서 응용 프로그램을 실행하면 문제가되지 않습니다. 그러나 AWS, Docker 또는 GCP의 모든 지역에서 실행하면 문제가 발생합니다. 컴퓨터는 클라우드의 시간대가 아니기 때문입니다. 코드에서 올바른 시간대를 설정해야합니다. 예 : 아시아 / 타이페이. 그런 다음 AWS, Docker 또는 GCP에서 수정됩니다.
public class App {
public static void main(String[] args) {
Instant now = Instant.now();
ZoneId zoneId = ZoneId.of("Australia/Sydney");
ZonedDateTime dateAndTimeInLA = ZonedDateTime.ofInstant(now, zoneId);
try {
Date ans = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateAndTimeInLA.toString().substring(0, 19).replace("T", " "));
System.out.println("ans="+ans);
} catch (ParseException e) {
}
Date wrongAns = Date.from(java.time.ZonedDateTime.ofInstant(now, zoneId).toInstant());
System.out.println("wrongAns="+wrongAns);
}
}
ans=Mon Jun 18 01:07:56 CEST 2018
, 이는 정확하지 않은 다음 wrongAns=Sun Jun 17 17:07:56 CEST 2018
, 맞습니다.
받아 들인 대답이 저에게 효과가 없었습니다. 반환 된 날짜는 항상 원래 시간대의 날짜가 아니라 현지 날짜입니다. 저는 UTC + 2에 살고 있습니다.
//This did not work for me
Date.from(java.time.ZonedDateTime.now().toInstant());
ZonedDateTime에서 올바른 날짜를 가져 오는 두 가지 다른 방법을 생각해 냈습니다.
이 ZonedDateTime for Hawaii가 있다고 가정합니다.
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneId.of("US/Hawaii"); // UTC-10
또는 원래 요청한 UTC의 경우
Instant zulu = Instant.now(); // GMT, UTC+0
ZonedDateTime zdt = zulu.atZone(ZoneId.of("UTC"));
대안 1
java.sql.Timestamp를 사용할 수 있습니다. 간단하지만 프로그래밍 무결성에도 영향을 미칠 것입니다.
Date date1 = Timestamp.valueOf(zdt.toLocalDateTime());
대안 2
millis에서 Date를 만듭니다 ( 앞서 여기 에서 답변 함 ). 로컬 ZoneOffset은 필수입니다.
ZoneOffset localOffset = ZoneOffset.systemDefault().getRules().getOffset(LocalDateTime.now());
long zonedMillis = 1000L * zdt.toLocalDateTime().toEpochSecond(localOffset) + zdt.toLocalDateTime().getNano() / 1000000L;
Date date2 = new Date(zonedMillis);
beehuang과 같은 도커 애플리케이션의 경우 시간대를 설정해야합니다.
또는 withZoneSameLocal 을 사용할 수 있습니다 . 예를 들면 :
2014-07-01T00 : 00 + 02 : 00 [GMT + 02 : 00]는
Date.from(zonedDateTime.withZoneSameLocal(ZoneId.systemDefault()).toInstant())
에 7월 1일 중부 유럽 표준시 00시 00분 0초 2014 화 및로
Date.from(zonedDateTime.toInstant())
~ 2014 년 6 월 30 일 월요일 22:00:00 UTC
지금 만 관심이 있다면 다음을 사용하십시오.
Date d = new Date();
java.util.Date
있으며java.sql.Date
.