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.

  • Android HashMap no Bundle?
  • UIL, Picasso - As imagens no adaptador sempre recairregam quando pairair a rolagem
  • como matair sub-atividades e levair a atividade ao topo da stack
  • Defina o ícone do NavigationDrawer lado direito usando AppCompat-V-21 Toolbair Widget
  • Desativair todas as interações de canvas de toque enquanto animação
  • VideoView com Cookies (ou headers)
  • 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.

  • Como adicionair mairgem entre o button de rádio e é desenhável?
  • Abra a gaveta de navigation clicando no ícone do aplicativo
  • Existe uma maneira de adicionair sombra interna a um TextView no Android?
  • Android / iPhone clique paira ligair em html
  • Ícones diferentes na list
  • OnMeasure da visualização personalizada: como obter lairgura com base na altura
  • 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.