2010-05-20 3 views
11

SOAP 웹 서비스에서 timzone 정보없이 datetime을받습니다. 따라서 축 디시리얼라이저는 UTC로 가정합니다. 그러나 datetime은 시드니 시간대에 있습니다. 나는 시간대 오프셋을 빼서 문제를 해결했다.Java에서 시간을 변경하지 않고 시간대 변경

Calendar trade_date = trade.getTradeDateTime(); 
TimeZone est_tz = TimeZone.getTimeZone("Australia/Sydney"); 
long millis = trade_date.getTimeInMillis() - est_tz.getRawOffset(); 
trade_date.setTimeZone(est_tz); 
trade_date.setTimeInMillis(millis); 

그러나이 솔루션이 일광 절약 시간제를 고려하는지 잘 모르겠습니다. 모든 작업은 UTC 시간이기 때문에해야한다고 생각합니다. Java에서 시간을 조작 한 경험이 있습니까? 이 문제를 해결하는 방법에 대한 더 나은 아이디어?

+1

나는 항상 지금까지, 그리고 고정 된 유일한 단위를 사용하여 날짜를 모든 언어로 조작하십시오. 그 단위는 두 번째 (또는 밀리 초)입니다. 59 또는 61 초가 걸리며 23 또는 25 시간이 걸립니다. 60 * 60 +/- 1 초 등의 시간이 있습니다. 모든 날짜는 기원 이후 (밀리) 초로 저장됩니다. 그것이 그들이 DB에있는 방식입니다. 그것이 정렬 된 방식입니다. 내가 시간대/yyyy-mm-dd를 수행하는 유일한 시간은 사용자에게 표시되어야 할 때 (또는 날짜가 초 단위로 표현 가능하다는 것을 이해하지 못하는 깨진 API를 사용할 때)입니다. – SyntaxT3rr0r

+0

@WizardOfOdds. 그것은 당연한 조언이지만 OP는 웹 서비스 (아마도 제 3 자)로부터 타임 스탬프를 받고 제 3 자 라이브러리를 사용하여 요청을 처리하는 것으로 명확히 게시했습니다. 분명히 그의 직접 통제에서 벗어나는 것들이 몇 가지 있으며, 표준 시간대에서 시간대로 변환하는 것은 java.util.Calendar를 사용하면 분명히 솔직하지 않을 것입니다. –

+0

의견을 보내 주셔서 감사합니다. Axis를 사용하여 WSDL 파일에서 웹 서비스 스텁을 생성합니다. 제 3 자 웹 서비스에 연결하기 위해 생성 된 클래스를 사용하고 있습니다. 사실, 표준 시간대 정보 또는 UTC로 날짜/시간 필드를 전송해야합니다. Axis에서 기대하는 것입니다. 하지만 그건 내 선택이 아니야. –

답변

-1

정확한 시간대 세트와 함께 수신 된 날짜 시간 문자열을 다시 채우도록 결정했습니다. 이 또한 고려해야 일광 절약 :

public class DateTest { 

    private static SimpleDateFormat soapdatetime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     TimeZone oztz = TimeZone.getTimeZone("Australia/Sydney"); 
     TimeZone gmtz = TimeZone.getTimeZone("GMT"); 
     Calendar datetime = Calendar.getInstance(gmtz); 

     soapdatetime.setTimeZone(gmtz); 
     String soap_datetime = soapdatetime.format(datetime.getTime()); 
     System.out.println(soap_datetime); 

     soapdatetime.setTimeZone(oztz); 
     datetime.setTimeZone(oztz); 
     try { 
      datetime.setTime(
        soapdatetime.parse(soap_datetime) 
      ); 
     } catch (ParseException e) { 
      e.printStackTrace(); 
     } 

     soapdatetime.setTimeZone(gmtz); 
     soap_datetime = soapdatetime.format(datetime.getTime()); 
     System.out.println(soap_datetime); 
    } 
} 
16

자바에서 날짜를 수행해야하는 바보를 불쌍히 여깁니다.

당신이 한 일은 거의 일광 절약 시간 전환으로 잘못 될 것입니다. 가장 좋은 방법은 아마도 새로운 Calendar 객체를 생성하고, 그 위에 Timezone을 설정 한 다음, Date, Date, Date, Date, Time, .

편집 :
이 행복 모두를 유지하려면, 당신은 아마이 작업을 수행해야한다 : 당신이 어떤 사용되지 않는 방법을 사용하지 않을

다음
Calendar utcTime = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 
Calendar sydneyTime = Calendar.getInstance(TimeZone.getTimeZone("Australia/Sydney"); 
utcTime.setTime(trade_date); 
for (int i = 0; i < Calendar.FIELD_COUNT; i++) { 
    sydneyTime.set(i, utcTime.get(i)); 
} 

.

+0

-1 : java.util.Date 클래스 –

+0

의 사용되지 않는 메소드의 사용을 제안하려면, 다음과 같이합니다 : newCalendar.set (oldCalendar.get (Calender.YEAR), oldCalendar.get (Calendar.MONTH), ..., oldCalendar.get Calendar.SECOND)); – wds

+1

@Alexander Pogrebnyak : 사용자가 어두운면으로 연결되지 않도록 답변을 업데이트했습니다. –

3

그러나이 솔루션이 일지라도 계정에 일광 절약 시간제를 적용하는지 확실하지 않습니다. 나는 그것이해야한다고 생각한다. 왜냐하면 모든 작업은 UTC 시간이기 때문이다.

예. UTC 오프셋에 영향을 미치기 때문에 일광 절약 시간을 고려해야합니다.

Java에서 시간을 조작 한 경험이 있습니까? 이 문제를 해결하는 방법에 대한 더 나은 아이디어?

Joda-Time은 더 나은 시간 API입니다. 아마도 다음 스 니펫이 도움이 될 수 있습니다.

DateTimeZone zone; // TODO : get zone 
DateTime fixedTimestamp = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond, zone); 

JodaTime 유형도 변경 될 수 없으므로 이점이 있습니다.

+0

JodaTime에 대한 링크를 제공해 주셔서 감사합니다. 그러나, 나는 그 프로젝트를 위해 새로운 써드 파티 라이브러리를 소개하지 않을 것이다. 하지만 JodaTime을 고려해야합니다. –

+0

Joda-Time은 타사 라이브러리를 추가하는 데는 가치가 있습니다. 잘 착용되고 입증 된 제품. java.util.Date 및 Calendar 클래스는 악명이 높습니다. –

2

내가 일반적으로는

Calendar trade_date_utc = trade.getTradeDateTime(); 
TimeZone est_tz = TimeZone.getTimeZone("Australia/Sydney"); 
Calendar trade_date = Calendar.GetInstance(est_tz); 
trade_date.setTimeInMillis(millis); 
4

내가이 나를 위해 좋은 시작과 내가하지 않았다 접근했다 responce 6의 사람에게 감사하고 싶어요이 방법을 수행하십시오 중히 여기다. 프로덕션 코드 수준으로 가져 오는 데 필요한 몇 가지 추가 단계가 있습니다. 특히 DST_OFFSET 및 ZONE_OFFSET에 필요한 단계를 준수하십시오. 필자가 생각해 낸 솔루션을 공유하고 싶습니다.

입력 된 Calendar 개체에서 시간이 소요되고 출력 시간으로 복사되고 새 표준 시간대가 출력으로 설정됩니다. 이것은 데이터베이스에서 문자 그대로 시간을 가져오고 시간을 변경하지 않고 표준 시간대를 설정할 때 사용됩니다.

public static Calendar setNewTimeZoneCopyOldTime(Calendar inputTime, 
     TimeZone timeZone) { 
    if((inputTime == null) || (timeZone == null)) { return(null); } 

    Calendar outputTime = Calendar.getInstance(timeZone); 
    for(int i = 0; i < Calendar.FIELD_COUNT; i++) { 
     if((i != Calendar.ZONE_OFFSET) && (i != Calendar.DST_OFFSET)) { 
      outputTime.set(i, inputTime.get(i)); 
     } 
    } 

    return((Calendar) outputTime.clone()); 
} 
0

당신은 엉망 업 웹 서비스에서 ISO 8601 스타일 문자열을 받고 있습니까? 그렇다면 Joda-Time 2.3 라이브러리는 이것을 매우 쉽게 만듭니다.

표준 시간대 오프셋이없는 ISO 8601 문자열을 가져 오는 경우 표준 시간대 개체를 DateTime 생성자에 전달합니다. 09 :

실행
System.out.println("dateTime: " + dateTime); 

...

dateTime: 2014-01-02T03:00:00.000+11:00 
0
@Test 
public void tzTest() { 
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z"); 
    TimeZone tz1 = TimeZone.getTimeZone("Europe/Moscow"); 
    Calendar cal1 = Calendar.getInstance(tz1); 
    long l1 = cal1.getTimeInMillis(); 
    df.setTimeZone(tz1); 
    System.out.println(df.format(cal1.getTime())); 
    System.out.println(l1); 
    TimeZone tz2 = TimeZone.getTimeZone("Africa/Douala"); 
    Calendar cal2 = Calendar.getInstance(tz2); 
    long l2 = l1 + tz1.getRawOffset() - tz2.getRawOffset(); 
    cal2.setTimeInMillis(l2); 
    df.setTimeZone(tz2); 
    System.out.println(df.format(cal2.getTime())); 
    System.out.println(l2); 
    assertNotEquals(l2, l1); 
} 


이 CalendarTest
2016년 6월 30일 (19)을 실행 덤프가 콘솔로

DateTimeZone timeZone = DateTimeZone.forID("Australia/Sydney"); 
String input = "2014-01-02T03:00:00"; // Note the lack of time zone offset at end. 
DateTime dateTime = new DateTime(input, timeZone); 

... 16.522 0300
1467302956522,210
2016년 6월 30일 19 : 09 : 16.522 0100
1467310156522
테스트 실행 : 1, 실패 : 0, 오류 : 0, 건너 뛴 : 0, 시간이 경과 : 0.137 초

관련 문제