2016-07-14 2 views
0

다음 형식으로 정의 된대로 TimeZone의 POSIX 형식을 만들어야합니다.Java TimeZone 및 Linux TimeZone 일광 절약 시간제가 일치하지 않습니다.

"미국/뉴욕"에 대한 예를 들어
std offset dst [offset],start[/time],end[/time] 

는 POSIX 형식은 M11.1.0 EST + 5EDT, M3.2.0/2 지금 값 M3.2.0/2에 표시됩니다/2

Mm.wd/t 형식.

월 m 일의 요일 d를 지정합니다. 일 d는 0 (일요일)과 6 사이 여야합니다. 주 w는 1과 5 사이 여야합니다. 주 1은 d 일이 발생한 첫 번째 주, 주 5는 달의 마지막 d 일을 지정합니다. I는 다음 링크 그래서

http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html

상기 예 상태에서 상기 설명 빌린 1 내지 12 개월 m이어야 UTC 오프셋 통상 5 시간이고; 이것이 본초 자오선의 서쪽에 있으므로 표지판은 양수입니다. 서머 타임은 3 월 두 번째 일요일 오전 2시에 시작하여 11 월 첫 번째 일요일 오전 2시에 끝납니다.

나는 리눅스 시간대 파일에서이를 확인하는 경우는/usr/share /은 zoneinfo/미국/뉴욕, 그것은 위의 값과 일치

EST5EDT, M3.2.0, M11.1.0

그러나 나는이를 구성 할 때 시간대를위한 자바에서 "미국/뉴욕"

이 내가로부터 정보를 추출하여 위의 문자열을 구축/I는 다음과 같은 문자열

EST-5EDT + 1, M2.1.1/2, M10.1.1를 얻을 다음 코드의 출력.

TimeZone timezone = TimeZone.getTimeZone("America/New_York"); 
System.out.println(timezone.toString()); 

출력

sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0] 

공지 아래로 리눅스 출력에 비해 11이어야 endMonth와 값 = 10.

+0

이 형식에 대한 링크를 POSIX 문서에 게시 할 수 있습니까? ? 나는 호기심이 많다. –

+0

예, 설명에서 언급했습니다. 그 내용은 다음과 같습니다. http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html로 –

+0

고마워,하지만, 공식 POSIX 문서 아니에요. 그것은 gnu.org의 일부 라이브러리입니다. 인터넷 검색은 POSIX 날짜 - 시간 형식으로 가정 된 다른 정의를 문서화 한 다른 출처로 안내했습니다. 그래서 나는 누군가가 권위있는 소식통을 올리기를 희망했다. –

답변

0

toString의 출력에 의존하는 것은 TimeZone 또는 SimpleTimeZone 클래스에서 형식에 대한 계약 상 보증이 없기 때문에 바람직하지 않습니다.

분명히 월 번호가 하나 떨어져 있습니다. 매월 첫 번째 주를 고려해야하기 때문에 한 달의 주간은 그리 간단하지 않습니다.

static String posixSpecFor(TimeZone tz) { 
    Formatter posixSpec = new Formatter(); 

    float offset = (float) tz.getRawOffset()/(1000 * 60 * 60) * -1; 
    posixSpec.format("%s%s%s", 
     tz.getDisplayName(false, TimeZone.SHORT), 
     offset >= 0 ? "+" : "", 
     new DecimalFormat("0.##").format(offset)); 

    if (tz.observesDaylightTime()) { 
     posixSpec.format("%s", tz.getDisplayName(true, TimeZone.SHORT)); 
    } 

    ZoneId zone = tz.toZoneId(); 

    TemporalField weekOfMonth = 
     WeekFields.of(DayOfWeek.SUNDAY, 7).weekOfMonth(); 
    int thisYear = Year.now(zone).getValue(); 

    List<ZoneOffsetTransitionRule> rules = 
     zone.getRules().getTransitionRules(); 
    if (rules.size() > 2) { 
     rules = rules.subList(0, 2); 
    } 

    for (ZoneOffsetTransitionRule rule : rules) { 
     posixSpec.format(",M%d.%d.%d/%s", 
      rule.getMonth().getValue(), 
      rule.createTransition(thisYear).getDateTimeBefore().get(
       weekOfMonth), 
      rule.getDayOfWeek().getValue() % 7, 
      rule.getLocalTime()); 
    } 

    return posixSpec.toString(); 
} 
+0

그레이트 !!!! 귀하의 코드에서 입력을 사용하여 다음 문자열을 구성 할 수있었습니다. EST + 5EDT, M3.2.0/2, M11.1.0/2 고맙습니다. –

0

다음은 I에서 POSIX 시간대 문자열을

공용 클래스 PosixTimeZone {

public String toPosixTZ(String timezoneStr) { 

    TimeZone timezone = TimeZone.getTimeZone(timezoneStr); 
    sop("timezoneStr", timezoneStr); 
    String posixTX = ""; 

    PosixTimeZoneData pTZData = new PosixTimeZoneData(timezone); 
    if (timezone.useDaylightTime()) { 
     posixTX = getPosixDSString(pTZData); 
    } else { 
     posixTX = getPosixString(pTZData); 
    } 
    return posixTX; 
} 

public static void main(String args[]) { 

    System.out.println("Posix TimeZone is " + new PosixTimeZone().toPosixTZ(args[0])); 
} 

private void sop(String varname, String meesage) { 
    System.out.println("**************: " + varname + " = " + meesage); 
} 

private String getPosixDSString(PosixTimeZoneData pTZData) { 
    String posixString = ""; 

    if ((pTZData.std != null && !pTZData.std.isEmpty()) 
      && (pTZData.stdOffset != null)//&& !pTZData.stdOffset.isEmpty()) 
      && (pTZData.dst != null && !pTZData.dst.isEmpty()) 
      && (pTZData.dstOffset != null)// && !pTZData.dstOffset.isEmpty()) 
      && (pTZData.start != null && !pTZData.start.isEmpty()) 
      && (pTZData.end != null && !pTZData.end.isEmpty())) { 
     posixString = String.format("%s%s%s%s,%s,%s", pTZData.std, pTZData.stdOffset, pTZData.dst, 
       pTZData.dstOffset, pTZData.start, pTZData.end); 
    } else { 
     sop("Error", "Invalid Parameters"); 
    } 

    return posixString; 
} 

private String getPosixString(PosixTimeZoneData pTZData) { 
    String posixString = ""; 

    if ((pTZData.std != null && !pTZData.std.isEmpty()) 
      && (pTZData.stdOffset != null && !pTZData.stdOffset.isEmpty())) { 
     posixString = String.format("%s%s", pTZData.std, pTZData.stdOffset); 
    } else { 
     sop("Error", "Invalid Parameters"); 
    } 

    return posixString; 
} 

class PosixTimeZoneData { 

    String std = ""; 
    String stdOffset = ""; 
    String dst = ""; 
    String dstOffset = ""; 
    String start = ""; 
    String end = ""; 

    private PosixTimeZoneData(TimeZone timeZone) { 

     std = timeZone.getDisplayName(false, TimeZone.SHORT); 
     int rawOffset = (timeZone.getRawOffset()/3600000) * -1; 
     stdOffset = (rawOffset >= 0) 
       ? ((rawOffset == 0) || (rawOffset == 1) ? "" : "+" + rawOffset) 
       : "" + rawOffset; 
     if (timeZone.useDaylightTime()) { 
      dst = timeZone.getDisplayName(true, TimeZone.SHORT); 

      int dstRawOffset = timeZone.getDSTSavings()/3600000; 
      dstOffset = (dstRawOffset >= 0) 
        ? ((dstRawOffset == 0) || (dstRawOffset == 1) ? "" : "+" + dstRawOffset) 
        : "" + dstRawOffset; 

      ZoneId zone = timeZone.toZoneId(); 

      TemporalField weekOfMonth 
        = WeekFields.of(DayOfWeek.SUNDAY, 7).weekOfMonth(); 
      int thisYear = Year.now(zone).getValue(); 

      List<ZoneOffsetTransitionRule> rules 
        = zone.getRules().getTransitionRules(); 
      if (rules != null && !rules.isEmpty()) { 
       if (rules.size() > 2) { 
        rules = rules.subList(0, 2); 
       } 

       start = String.format("M%d.%d.%d/%s", 
         rules.get(0).getMonth().getValue(), 
         rules.get(0).createTransition(thisYear).getDateTimeBefore().get(
         weekOfMonth), 
         rules.get(0).getDayOfWeek().getValue() % 7, 
         rules.get(0).getLocalTime().getHour()); 

       end = String.format("M%d.%d.%d/%s", 
         rules.get(1).getMonth().getValue(), 
         rules.get(1).createTransition(thisYear).getDateTimeBefore().get(
         weekOfMonth), 
         rules.get(1).getDayOfWeek().getValue() % 7, 
         rules.get(1).getLocalTime().getHour()); 

      } 
     } 
    } 

} 
을 구성하기 위해 사용하고있는 전체 코드입니다 :

나는 정보를 얻기 위해 자바의 문서화 된 공개 방법을 사용

}

+0

'rules'이 null인지 검사 할 필요가 없습니다. [메소드 계약] (https://docs.oracle.com/javase/8/docs/api/java/time/zone/ZoneRules.html#getTransitionRules--)에서는 "전환 규칙의 불변 목록, null이 아닙니다. " – VGR

+0

Ok. 그것을 바꿀 것입니다. 고맙습니다. –

관련 문제