2017-01-26 16 views
11

아래 코드는 Nougat과 Nougat에 대해 다른 결과를 제공합니다. 원하는 경우 직접 확인해보십시오. 왜 누군가가 나에게 설명하고 해결책을 줄 수 있다면 고맙겠습니다.GregorianCalendar setFirstDayOfWeek이 Nougat의 WEEK_OF_YEAR에 영향을 미치지 않습니다.

모든 Android 버전에서 첫 번째 요일에 따라 정확한 WEEK_OF_YEAR 값을 원합니다. 나는 시간표 응용 프로그램이 있고 gregianCalendar를 많이 사용하고 있으므로 다른 클래스/lib로 전환하는 기분이 들지 않습니다. 당신이 release notes for Nougat 보면

//default first day of the week is Monday for replication. I live in the Netherlands, it's weird. 
    Locale l = new Locale("nl", "NL"); 

    GregorianCalendar test = new GregorianCalendar(l); 
    test.set(Calendar.YEAR, 2017); 
    test.set(Calendar.MONTH, 0); 
    test.set(Calendar.DAY_OF_MONTH, 29);//this is a Sunday 

    int week = test.get(Calendar.WEEK_OF_YEAR);//should be 4 
    test.setFirstDayOfWeek(1);//Set it to Sunday 
    int week2 = test.get(Calendar.WEEK_OF_YEAR);//should be 5 but is 4 below nougat??? 
+0

설명해 주셔서 감사합니다. 나는 내 대답이 문제의 방향으로 일반적인 고개를 끄는 것 (Nougat app and system locale과 일치 함)을 제외하고는 지금 당신에게 유용 할 것이라고 생각하지 않는다. 더 나은 답변을 얻기 위해 아마도 더 많은 것을 명확히 할 수 있습니다. 샘플 코드에서 Locale을 설정하여 문제를 재현하거나 앱 내부에서 수행하고자하는 작업입니까? 어쨌든 고마워, –

+0

. Locale은 문제를 재현하기위한 것입니다. –

답변

3

당신은 로케일에 대한 지원이 향상되는 것을 볼 수 있습니다.

특히,

이전에 안드로이드 7.0에, 안드로이드는 항상 성공적으로 응용 프로그램 및 시스템 로케일과 일치하지 수 있습니다.

나도 내 장치에서 이것을 알아 챘습니다. 내 전화는 영어 (호주) 로켈로 설정됩니다. , 누가 이전

DateTimeFormat.forPattern("dd MMMM").print(new LocalDate(2017,1,29)); 

29 Jan (더 풀 스톱/기간)을 인쇄하지하지만 누가 후에는 (기간) 29 Jan.를 인쇄합니다.

정확한 세부 정보를 제공하기는 어렵지만 귀하의 경우에 해당되는 것처럼 보입니다. Post-Nougat를 사용하면 휴대 전화가 로케일의 첫 번째 요일을 포함하여 앱 및 시스템 로케일을보다 잘 일치시킬 수 있습니다. 어쨌든 소스 코드에 노출 된 Java 클래스가 아닌 libcore 내부에서 호출이 처리되므로 근본 원인을 찾기 위해 디버거를 단계별로 실행해야합니다.

안드로이드 장치가 잘못 년/첫 주 올해의 첫 날을보고하는 경우, 당신은 주위 일 외에 할 수있는 작은있을 것입니다 :

if (android.os.Build.VERSION.SDK_INT < 24) { 
    //pre-Nougat logic 
} 
else { 
    //Nougat/post-Nougat logic 
} 

또한 아마도 enhanced replacement for GregorianCalendar를 사용하여 시도해 볼 수도 있습니다 (SDK 24에 추가)를 사용하여 문제를 해결하십시오.

Joda-time과 같은 클래스를 사용하거나 새로운 JSR-310 클래스를 사용하는 경우 (ThreeTen 백 포트를 통해) 사용자는 GregorianCalendar을 사용하지 않고도 원하는 것을 얻을 수 있습니다. 일반적으로이 클래스는 사용하기가 훨씬 쉽고 버그가 발생하기 쉽습니다. 많은 개발자들이 이미 이런 문제로 인해 java.util.Calendarjava.util.Date을 포기했습니다. to this canonical question 자세한 내용은

을 사용하여 GregorianCalendar 개체를 LocalDate으로 변환 할 수 있습니다. 이 클래스는 ISO 표준을 사용하며 첫 번째 요일은 항상 월요일입니다. 그런 다음 자신이 원하는 논리를 쓸 것입니다. 그런 다음 GregorianCalendar의 문제는 주어진 로케일의 첫 번째 주를 검색하는 단순한 문제로 "격리"됩니다. 앱에서 서버에 대한 호출을 통합하는 경우 API 호출에서 첫 번째 요일에 대신 게재 할 수 있습니다.

업데이트 :

주 시간대의 행동이 Android O에 업데이트되었습니다

시간대 이름 구문 분석이 변경된 다음과 같이

추가 로케일 및 국제화 관련 변경 사항은 다음과 같습니다. 이전에는 Android 기기가 부팅시 샘플링 된 시스템 클럭 값을 사용하여 날짜 시간을 분석하는 데 사용 된 시간대 이름을 캐시했습니다. 결과적으로 시스템 시계가 부팅시 또는 다른 드문 경우에 파싱에 부정적인 영향을 미칠 수 있습니다. 일반적으로 구문 분석 논리는 표준 시간대 이름을 구문 분석 할 때 ICU와 현재 시스템 시계 값을 사용합니다. 이 변경은 앱이 SimpleDateFormat과 같은 클래스를 사용할 때 이전 Android 버전과 다를 수있는 더 정확한 결과를 제공합니다. 안드로이드 O는 ICU의 버전을 버전 58로 업데이트합니다.

+0

기본적으로 모든 Android 버전에서주의 첫날에 따라 올바른 WEEK_OF_YEAR 값이 필요합니다. 나는 timehseet 응용 프로그램을 가지고 있고 gregianCalendar를 많이 사용하고 있으므로 다른 클래스/lib로 전환하는 기분이 들지 않습니다. –

-1

나는이 문제가 당신이 달을 설정하고있는 라인에 있다고 생각합니다.

// 여기서 month 매개 변수는 Calendar.MONTH가 허용하는 입력이 0에서 시작하더라도 배열이 1에서 12 사이에 있기 때문에 문제를 일으킬 수있는 값으로 0을 전달합니다. .

또는 당신은 또한 달 사용 1 월에 설정이으로 변경할 수 있습니다

test.set(Calendar.MONTH, Calendar.JANUARY); 

// 또한 여기이 줄을 시도하고이 해결해야

test.setFirstDayOfWeek(Calendar.SUNDAY);//Set it to Sunday 

로 변경하려면 문제.

+1

죄송하지만, 사실이 아닙니다. Calendar.JANUARY의 값도 0입니다. –

+0

Calendar.JANUARY를 사용하는 유일한 이유는 JANUARY의 값이 0에서 다른 값으로 변경된다고 가정하면 코드를 업데이트 할 필요가 없습니다. –