[java] 주어진 시간대에 대한 날짜 / 시간 변환-Java

이 GMT 타임 스탬프를 GMT + 13으로 변환하고 싶습니다.

2011-10-06 03:35:05

이 아주 기본적인 작업을 수행하기 위해 DateFormat, TimeZone, Date, GregorianCalendar 등의 약 100 가지 다른 조합을 시도했습니다.

이 코드는 현재 시간에 대해 원하는 작업을 수행합니다.

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));

로컬 시스템의 TimeZone이 사용됩니다. 왜 그런 겁니까? “new Date ()”가 UTC + 0 시간을 반환 할 때 시간을 밀리 초로 설정하면 더 이상 시간이 UTC로 간주되지 않는 이유는 무엇입니까?

해도 될까요:

  1. 개체에 시간 설정 (Calendar / Date / TimeStamp)
  2. (가능) 초기 타임 스탬프의 TimeZone 설정 (calendar.setTimeZone (…))
  3. 새 TimeZone (formatter.setTimeZone (…)))으로 타임 스탬프 서식 지정
  4. 새로운 시간대 시간이있는 문자열을 반환합니다. (formatter.format (calendar.getTime ()))

도움을 주셔서 미리 감사드립니다 : D



답변

저에게 가장 간단한 방법은 다음과 같습니다.

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()));


답변

컴퓨터 시간이 어떻게 작동하는지 이해하는 것은 매우 중요합니다. 즉, 실시간처럼 컴퓨터 시간을 처리 할 수 ​​있도록 API가 생성되면 실시간으로 처리 할 수있는 방식으로 작동해야한다는 데 동의합니다. 대부분의 경우 이것이 사실이지만주의가 필요한 몇 가지 주요 감독이 있습니다.

어쨌든 나는 탈선 !! UTC 오프셋이있는 경우 (GMT 오프셋보다 UTC에서 작업하는 것이 더 좋음) 시간을 밀리 초 단위로 계산하여 타임 스탬프에 추가 할 수 있습니다. SQL 타임 스탬프는 에포크로부터의 경과가 계산되는 방식이 항상 동일하지는 않기 때문에 Java 타임 스탬프와 다를 수 있습니다. 데이터베이스 기술 및 운영 체제에 따라 다릅니다.

System.currentTimeMillis ()를 타임 스탬프로 사용하는 것이 좋습니다. SQL 타임 스탬프를 Java Date 객체로 변환하는 것에 대해 걱정하지 않고 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());

도움이 되었기를 바랍니다.


답변

항상 그렇듯이 Java의 날짜 및 시간에 대한 이 기사 를 읽고 이해할 수 있도록하는 것이 좋습니다 .

기본 아이디어는 ‘내부에서’모든 것이 에포크 이후 UTC 밀리 초 단위로 수행된다는 것입니다. 즉, 사용자에 대한 문자열 형식을 제외하고 시간대를 전혀 사용하지 않고 작업하는 것이 가장 쉽습니다.

따라서 귀하가 제안한 대부분의 단계를 건너 뛸 것입니다.

  1. 개체 (날짜, 달력 등)에 시간을 설정합니다.
  2. 포맷터 개체에 표준 시간대를 설정합니다.
  3. 포맷터에서 문자열을 반환합니다.

또는 Joda time을 사용할 수 있습니다 . 훨씬 더 직관적 인 datetime API라고 들었습니다.


답변

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 형식입니다. 중간의 SPACE를 T.

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

LocalDateTime

LocalDateTime입력에 UTC 또는 시간대에 대한 정보가 없기 때문에 이제 a로 구문 분석 하십시오. A LocalDateTime에는 오프셋이나 시간대에 대한 개념이 없으므로 타임 라인의 실제 순간을 않습니다 .

LocalDateTime ldt = LocalDateTime.parse( input );

ZoneOffset

비즈니스 컨텍스트에서이 문자열의 의도는 UTC보다 13 시간 앞선 순간을 나타내는 것임을 알고있는 것 같습니다. 그래서 우리는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)과 같은 이상을 처리하기위한 규칙들의 집합. 따라서 우리는 단순한 오프셋 ZoneIdZonedDateTime아닌 a 를 지정할 수 있습니다 .

적절한 시간대 이름을 지정하십시오 . EST또는 IST과 같은 3-4 자의 약어를 사용하지 마십시오. 표준 시간대가 아니고 고유하지도 않습니다 (!). 예를 들면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 UTC가 시작된 후의 밀리 초와 같은 epoch의 카운트로 날짜-시간 값을 처리하지 않는 것이 좋습니다. 하지만 필요한 경우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 (2011 년 10 월 5 일 수요일 12:12:15 GMT)
  • 2011-10-06T01:12:15+13:00[Pacific/Auckland] (2011 년 10 월 6 일 목요일 뉴질랜드 오클랜드에서 01:12:15).

문자열 생성

표준 ISO 8601 형식으로 문자열을 생성하려면 toString. ZonedDateTime시간대 이름을 대괄호로 묶어 표준 형식 을 현명하게 확장합니다.

String output = zdt.toString();

다른 형식의 경우 Stack Overflow에서 DateTimeFormatter클래스를 검색하십시오 . 이미 여러 번 다루었습니다.

a FormatStyleLocale.

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의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이러한 클래스는 같은 귀찮은 된 날짜 – 시간의 수업을 대신하는 java.util.Date, .Calendar, java.text.SimpleDateFormat.

Joda 타임 지금 프로젝트, 유지 관리 모드 , java.time로 마이그레이션을 조언한다.

자세한 내용은 Oracle Tutorial을 참조하십시오 . 그리고 많은 예제와 설명을 위해 Stack Overflow를 검색하십시오.

많은 java.time 기능은 자바 6 & 7 백 포팅 ThreeTen – 백 포트 추가에 적응 안드로이드ThreeTenABP (참조 … 사용 방법 ).

ThreeTen – 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 java.time에 향후 추가 될 수있는 가능성을 입증하는 근거입니다. 여기 Interval에서 YearWeek,, 등과 같은 유용한 클래스를 찾을 수 있습니다 YearQuarter.


답변

솔루션은 실제로 매우 간단합니다 (순수하고 단순한 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


답변

살펴 보았고 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);


답변

오프셋 값을 사용하여 처리 할 수 ​​있습니다.

 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