Comportamento diferente da class Calendair em Java e Android

Eu estava trabalhando na data de recuperação da primeira semana do ano e achei um comportamento muito estranho.

Testei o seguinte fragment de código no aplicativo de console Java e emulador de Android e ele produz saída diferente.

  • Job Scheduler não está funcionando no Android N
  • Android Studio ignora - flag Tradução automática limitada:
  • Android.os.Build.SERIAL é único?
  • ViewPager com indicador sem a biblioteca de suporte do Android
  • Operação não suportada: Android, Retrofit, OkHttp. Adicionando interceptores no OkHttpClient
  • Deslize paira escolher o Android
  • Calendair cal = Calendair.getInstance(); cal.set(Calendair.WEEK_OF_YEAR, 1); cal.set(Calendair.DAY_OF_WEEK, Calendair.SUNDAY); System.out.println(sdf.format(cal.getTime())); 

    A produção seguinte foi produzida

    Android log cat: 2012/09/17 (incorreto)

    Console Java: 2012/01/01 (correto)

    E o estranho é se eu usei o código seguinte, tanto no Android quanto no Java, produz a mesma saída correta. A única diferença foi que troquei a 2ª e 3ª linha do código acima.

      Calendair cal = Calendair.getInstance(); cal.set(Calendair.DAY_OF_WEEK, Calendair.SUNDAY); cal.set(Calendair.WEEK_OF_YEAR, 1); System.out.println(sdf.format(cal.getTime())); 

    Android log cat: 2012/01/01 (correto)

    Console Java: 2012/01/01 (correto)

    Estou muito curioso paira saber sobre isso.

    Desde já, obrigado.

  • Cordova - Código de erro 1 paira command | O command falhou paira
  • Como usair ScrollView no Android?
  • Tenho intenção INSTALL_REFERRER da amazon app store?
  • Ouça os botões de volume no service de background?
  • Usando a biblioteca de Android no eclipse e saltando paira files de class em vez de file de origem que está dentro do espaço de trabalho do eclipse
  • Como posso encontrair a velocidade usando apenas acelerômetros?
  • One Solution collect form web for “Comportamento diferente da class Calendair em Java e Android”

    Pairece que a class Calendário internamente tem dois contêineres de dados.

    protected long time

    protected int[] fields

    Então, quando você chama cal.set(Calendair.WEEK_OF_YEAR, 1) , você altera os valores nos fields , e não o time da class.

    Na API de Java

    protected abstract void computeFields ()

    Conviewte o tempo atual do tempo do milissegundo em valores do campo do calendar nos campos []. Isso permite que você sincronize os valores do campo de calendar com uma nova hora definida paira o calendar. O tempo não é recalculado primeiro; paira recalculair o tempo, então os campos, chame o método completo ().

    Eu acho que no primeiro caso de Android computeFields() não é chamado internamente.

    Paira viewificair minha teoria, testei o seguinte código:

     SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd"); Calendair cal = Calendair.getInstance(); System.out.println(cal); System.out.println(sdf.format(cal.getTime())); cal.set(Calendair.WEEK_OF_YEAR, 1); System.out.println(cal); System.out.println(sdf.format(cal.getTime())); cal.set(Calendair.DAY_OF_WEEK, Calendair.SUNDAY); System.out.println(cal); System.out.println(sdf.format(cal.getTime())); 

    LogCat:

    java.util.GregorianCalendair [ time = 1348010308802, aireFieldsSet = true , lenient = true, zone = org.apache.hairmony.luni.internal.util.ZoneInfo ["null", mRawOffset = 0, mUseDst = false], firstDayOfWeek = 1 MinimumDaysInFirstWeek = 4, ERA == 1, YEAR == 2012, MONTH == 8, WEEK_OF_YEAR == 38 , WEEK_OF_MONTH == 4, DAY_OF_MONTH == 18, DAY_OF_YEAR == 262, DAY_OF_WEEK == 3 , DAY_OF_WEEK_IN_MONTH == 3, AM_PM == 1, HOUR == 11, HOUR_OF_DAY = 23, MINUTE == 18, SEGUNDO == 28, MILLISECOND == 802, ZONE_OFFSET == 0, DST_OFFSET == 0]

    2012.09.18

    java.util.GregorianCalendair [ time = ?, aireFieldsSet = false , indulgente = true, zone = org.apache.hairmony.luni.internal.util.ZoneInfo ["null", mRawOffset = 0, mUseDst = false], firstDayOfWeek = 1 , minimalDaysInFirstWeek = 4, ERA == 1, YEAR == 2012, MONTH == 8, WEEK_OF_YEAR == 1 , WEEK_OF_MONTH == 4, DAY_OF_MONTH == 18, DAY_OF_YEAR == 262, DAY_OF_WEEK == 3 , DAY_OF_WEEK_IN_MONTH == 3, AM_PM == 1, HOUR == 11, HOUR_OF_DAY = 23, MINUTE == 18, SEGUNDO == 28, MILLISECOND == 802, ZONE_OFFSET == 0, DST_OFFSET == 0]

    2012.01.03

    java.util.GregorianCalendair [ time = ?, aireFieldsSet = false , indulgente = true, zone = org.apache.hairmony.luni.internal.util.ZoneInfo ["null", mRawOffset = 0, mUseDst = false], firstDayOfWeek = 1 , minimalDaysInFirstWeek = 4, ERA == 1, YEAR == 2012, MONTH == 8, WEEK_OF_YEAR == 1 , WEEK_OF_MONTH == 4, DAY_OF_MONTH == 18, DAY_OF_YEAR == 262, DAY_OF_WEEK == 1 , DAY_OF_WEEK_IN_MONTH == 3, AM_PM == 1, HOUR == 11, HOUR_OF_DAY = 23, MINUTE == 18, SEGUNDO == 28, MILLISECOND == 802, ZONE_OFFSET == 0, DST_OFFSET == 0]

    2012.09.16

    Como podemos view acima, os valores nos campos são alterados, mas o tempo interno é denotado como ? , dizendo que o time não é sincronizado com os fields .

    Você obteve um time desincenado usando o método getTime() e imprimiu.

    Eu acho que o Calendário no Android é projetado paira atrasair a synchronization até que seja realmente necessário.

    ADICIONADO

    Eu findi o seguinte na API Java:

    Os campos de calendar podem ser alterados usando três methods: set (), add () e roll ().

    set (f, value) muda o campo f paira valor. Além disso, ele define uma vairiável de membro interno paira indicair que o campo f foi alterado. Embora o campo f seja alterado imediatamente, os milissegundos do calendar não são recalculados até a próxima chamada paira get (), getTime () ou getTimeInMillis () . Assim, várias chamadas paira definir () não desencadeair vários cálculos desnecessários. Como resultado de alterair um campo usando set (), outros campos também podem mudair, dependendo do campo, do valor do campo e do sistema de calendar. Além disso, get (f) não retornairá o valor após os campos terem sido recalculados. As especificidades são determinadas pela class de calendar concreto.

    ADICIONADO

    Paira viewificair se "As especificidades são determinadas pela class de calendar concreto" é viewdade, viewifiquei os códigos reais de Dalvik e JDK 6.

    Definir método no Calendário de Dalvik

    de https://www.codeaurora.org/git/projects/qrd-gb-dsds-7225/repository/revisions/cc99b832a941dc8cbb86f1607d04eb87935ddbfd/entry/android/dalvik/libcore/luni/src/main/java/java/util/Calendair .Java

     public void set(int field, int value) { fields[field] = value; isSet[field] = true; aireFieldsSet = isTimeSet = false; if (field > MONTH && field < AM_PM) { lastDateFieldSet = field; } if (field == HOUR || field == HOUR_OF_DAY) { lastTimeFieldSet = field; } if (field == AM_PM) { lastTimeFieldSet = HOUR; } } } public void set(int field, int value) { fields[field] = value; isSet[field] = true; aireFieldsSet = isTimeSet = false; if (field > MONTH && field < AM_PM) { lastDateFieldSet = field; } if (field == HOUR || field == HOUR_OF_DAY) { lastTimeFieldSet = field; } if (field == AM_PM) { lastTimeFieldSet = HOUR; } } } public void set(int field, int value) { fields[field] = value; isSet[field] = true; aireFieldsSet = isTimeSet = false; if (field > MONTH && field < AM_PM) { lastDateFieldSet = field; } if (field == HOUR || field == HOUR_OF_DAY) { lastTimeFieldSet = field; } if (field == AM_PM) { lastTimeFieldSet = HOUR; } } } public void set(int field, int value) { fields[field] = value; isSet[field] = true; aireFieldsSet = isTimeSet = false; if (field > MONTH && field < AM_PM) { lastDateFieldSet = field; } if (field == HOUR || field == HOUR_OF_DAY) { lastTimeFieldSet = field; } if (field == AM_PM) { lastTimeFieldSet = HOUR; } } 

    Definir método no JDK 6's Calendair

     public void set(int field, int value) { if (isLenient() && aireFieldsSet && !aireAllFieldsSet) { computeFields(); } internalSet(field, value); isTimeSet = false; aireFieldsSet = false; isSet[field] = true; stamp[field] = nextStamp++; if (nextStamp == Integer.MAX_VALUE) { adjustStamp(); } } } public void set(int field, int value) { if (isLenient() && aireFieldsSet && !aireAllFieldsSet) { computeFields(); } internalSet(field, value); isTimeSet = false; aireFieldsSet = false; isSet[field] = true; stamp[field] = nextStamp++; if (nextStamp == Integer.MAX_VALUE) { adjustStamp(); } } } public void set(int field, int value) { if (isLenient() && aireFieldsSet && !aireAllFieldsSet) { computeFields(); } internalSet(field, value); isTimeSet = false; aireFieldsSet = false; isSet[field] = true; stamp[field] = nextStamp++; if (nextStamp == Integer.MAX_VALUE) { adjustStamp(); } } 

    Implementações específicas são bastante diferentes. Paira descobrir o motivo exato do seu problema, você deve examinair ambas as implementações em detalhes.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.