[java] GregorianCalendar perikelen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Standeman
  • Registratie: November 2000
  • Laatst online: 10:33

Standeman

Prutser 1e klasse

Topicstarter
Ik was probeerde een bug op te lossen in de creatie van wat datums. Na wat geklooi en het verwijderen van niet ter zaken doende code kwam ik tot het volgende:

Java:
1
2
3
4
5
6
7
        Calendar c = GregorianCalendar.getInstance();
        c.set(Calendar.YEAR, 2011);
        c.set(Calendar.DAY_OF_YEAR, 1);
        System.out.println(c.getTime());
        Calendar temp = GregorianCalendar.getInstance();
        c.set(Calendar.DAY_OF_WEEK, temp.get(Calendar.DAY_OF_WEEK));
        System.out.println(c.getTime());


resultaat van de println's
code:
1
2
Sat Jan 01 14:36:49 CET 2011
Tue Dec 28 14:36:49 CET 2010


Echter:
Java:
1
2
3
4
5
6
7
        Calendar c = GregorianCalendar.getInstance();
        c.set(Calendar.YEAR, 2011);
        System.out.println(c.getTime());
        c.set(Calendar.DAY_OF_YEAR, 1);
        Calendar temp = GregorianCalendar.getInstance();
        c.set(Calendar.DAY_OF_WEEK, temp.get(Calendar.DAY_OF_WEEK));
        System.out.println(c.getTime());


resultaat van de println's
code:
1
2
Wed Oct 26 14:40:27 CEST 2011
Tue Oct 25 14:40:27 CEST 2011



Ik geloof dat ik gek/dom/scheel* wordt... Zo niet, dan heb ik misschien een bug in de GregorianCalendar class ontdekt :?


Zoek de verschillen! (Hint: het gaat primair om regel 2 van de output, daar zou imo hetzelfde uit moeten komen)

* doorkruisen wat niet van toepassing is

The ships hung in the sky in much the same way that bricks don’t.


Acties:
  • 0 Henk 'm!

Anoniem: 28557

Ik ben niet zo thuis in Java, maar dindag 28 december is de dinsdag (en dat is vandaag, dus wat je terug krijgt uit temp.get(..)) uit de week van 1 januari 2011.

edit:

Oh wacht, het verschil zit'm in dat je 2 keer hetzelfde uitvoert, alleen de 2e c.set(...) eerst voor en later na de print zet...

[ Voor 31% gewijzigd door Anoniem: 28557 op 26-10-2010 14:58 ]


Acties:
  • 0 Henk 'm!

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 02-07 19:31

Robtimus

me Robtimus no like you

Het verschil is de getTime() call tussen het zetten van de dag van het jaar en de dag van de week; enig experimenteren met Calendar.get laat hetzelfde gedrag zien. Het lijkt erop dat het zetten van de dag van de week de laatste verandering van de dag van het jaar, maar ook de dag van de maand, teniet doet. Ik zou hiervoor zeker in de Java bug database kijken, en deze aanmelden als hij nog niet is aangemeld.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Acties:
  • 0 Henk 'm!

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
Lees de Javadoc, dit gedrag staat daarin duidelijk gedocumenteerd. Set voert de veranderingen niet volledig door, de wijzigingen worden pas doorgevoerd na het uitvoeren van een getTime() (of een get(..)).

In je eerste geval wordt de Calendar gewijzigd naar 1 januari 2011 en daarna naar de dinsdag in de week van 1 januari 2011 (of te wel 28 december 2010).
In je eerste geval wordt de Calendar gewijzigd naar 26 oktober 2011, en daarna naar de dinsdag in de week van 26 oktober 2011 (of te wel 25 oktober 2011). De set van DAY_OF_YEAR gaat verloren doordat je deze met set DAY_OF_WEEK 'overschrijft'. De andere velden van Calendar zoals maand, week ed zijn namelijk nog niet opnieuw berekend.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
        Calendar c = GregorianCalendar.getInstance();
// DAY_OF_MONTH = 26, DAY_OF_WEEK = TUESDAY, MONTH = OCTOBER, YEAR = 2010
        c.set(Calendar.YEAR, 2011);
// ... YEAR = 2011
        System.out.println(c.getTime());
// All fields recalculated : DAY_OF_MONTH = 26, DAY_OF_WEEK = WEDNESDAY, MONTH = OCTOBER, YEAR = 2011
        c.set(Calendar.DAY_OF_YEAR, 1);
// DAY_OF_MONTH = 26, DAY_OF_WEEK = WEDNESDAY, MONTH = OCTOBER, YEAR = 2011, DAY_OF_YEAR = 1 (DAY_OF_MONTH and MONTH not updated!)
        Calendar temp = GregorianCalendar.getInstance();
        c.set(Calendar.DAY_OF_WEEK, temp.get(Calendar.DAY_OF_WEEK));
// .. DAY_OF_WEEK = TUESDAY, update of DAY_OF_YEAR is lost
        System.out.println(c.getTime());
// All fields recalculated: DAY_OF_MONTH = 25, DAY_OF_WEEK = TUESDAY, MONTH = OCTOBER, YEAR = 2011

[ Voor 39% gewijzigd door Remus op 26-10-2010 15:19 ]


Acties:
  • 0 Henk 'm!

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 02-07 19:31

Robtimus

me Robtimus no like you

Ok, dus geen bug, maar vreemd is het toch wel. Bij wijze van test heb ik ipv DAY_OF_YEAR op 1 zetten de maand op Calendar.JANUARY gezet en de DATE (is DATE_OF_MONTH) op 1. Resultaat is 25 januari 2011. Dus wederom wordt een deel - de dag van de maand - keihard genegeerd, ook al is deze expliciet gezet.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Acties:
  • 0 Henk 'm!

  • Standeman
  • Registratie: November 2000
  • Laatst online: 10:33

Standeman

Prutser 1e klasse

Topicstarter
Remus schreef op dinsdag 26 oktober 2010 @ 15:10:
Lees de Javadoc, dit gedrag staat daarin duidelijk gedocumenteerd. Set voert de veranderingen niet volledig door, de wijzigingen worden pas doorgevoerd na het uitvoeren van een getTime() (of een get(..)).

In je eerste geval wordt de Calendar gewijzigd naar 1 januari 2011 en daarna naar de dinsdag in de week van 1 januari 2011 (of te wel 28 december 2010).
In je eerste geval wordt de Calendar gewijzigd naar 26 oktober 2011, en daarna naar de dinsdag in de week van 26 oktober 2011 (of te wel 25 oktober 2011). De set van DAY_OF_YEAR gaat verloren doordat je deze met set DAY_OF_WEEK 'overschrijft' (de andere velden van Calendar zoals maand, week ed zijn namelijk nog niet opnieuw berekend.
Duidelijk... dus het is gek/dom/scheel :P Ik zat voornamelijk in de doc van get te kijken of er iets raars was, niet in de set.

Volgende keer beter lezen dus....

Wel suf eigenlijk dat je bij het wijzigen van calendar geforceerd wordt om zo nu en dan getTime(), roll() of add() aan te roepen :/

[ Voor 5% gewijzigd door Standeman op 26-10-2010 15:25 ]

The ships hung in the sky in much the same way that bricks don’t.


Acties:
  • 0 Henk 'm!

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
IceManX schreef op dinsdag 26 oktober 2010 @ 15:15:
Ok, dus geen bug, maar vreemd is het toch wel. Bij wijze van test heb ik ipv DAY_OF_YEAR op 1 zetten de maand op Calendar.JANUARY gezet en de DATE (is DATE_OF_MONTH) op 1. Resultaat is 25 januari 2011. Dus wederom wordt een deel - de dag van de maand - keihard genegeerd, ook al is deze expliciet gezet.
De Java Calendar implementatie is inderdaad een beest, maar ook dit gedrag is gedefinieerd in de javadoc van Calendar. Je geeft overigens niet duidelijk aan in welke volgorde je fields hebt gezet
If there is any conflict in calendar field values, Calendar gives priorities to calendar fields that have been set more recently. The following are the default combinations of the calendar fields. The most recent combination, as determined by the most recently set single field, will be used.

For the date fields:

YEAR + MONTH + DAY_OF_MONTH
YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
YEAR + DAY_OF_YEAR
YEAR + DAY_OF_WEEK + WEEK_OF_YEAR

Acties:
  • 0 Henk 'm!

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 02-07 19:31

Robtimus

me Robtimus no like you

Ik gebruikte MONTH + DAY_OF_MONTH + DAY_OF_WEEK. Zelfs nu vind ik het opmerkelijk; ja ik verwachtte dat DAY_OF_WEEK de DAY_OF_MONTH zou overrulen, maar niet dat deze compleet genegeerd zou worden. Dus in plaats van 26-10-2010 -> 26-10-2011 -> 26-01-2011 -> 01-01-2011 -> 28-12-2010 heeft hij 26-10-2010 -> 26-10-2011 -> 26-01-2011 -> (sla 01-01-2011 over) 25-01-2011 gedaan. Ik blijf het apart vinden.

Maar dit probleem vindt blijkbaar alleen plaats zodra je dagen/maanden gaat combineren met weekdagen/weken; jaar + maand + dag is geen probleem, jaar + week + weekdag is geen probleem.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Acties:
  • 0 Henk 'm!

  • IntToStr
  • Registratie: December 2003
  • Nu online
De standaard Date en Calendar en zo zijn nogal vaag in gebruik. Je bent niet de eerste die rare dingen tegenkomt...

Een alternatief dat ik nog wel eens wil gebruiken als ik de kans heb bij de start van een project is JodaTime. Deze library is een stuk intuitiever.

Acties:
  • 0 Henk 'm!

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 02-07 19:31

Robtimus

me Robtimus no like you

En komt mogelijk in Java 7.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Acties:
  • 0 Henk 'm!

  • oeLangOetan
  • Registratie: Maart 2002
  • Laatst online: 05-06 18:00
nope, http://blogs.sun.com/mr/entry/plan_b_details, dat wordt op zijn minst wachten tot in 2013

Acties:
  • 0 Henk 'm!

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 02-07 19:31

Robtimus

me Robtimus no like you

Of gewoon de JAR file downloaden en gebruiken.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01-07 14:32
Dit kan wat mij betreft direct door naar het slechte programmeervoorbeeldentopic. Nee, niet vanwege Standeman's code, maar vanwege de klasse die z'n interne representatie wijzigt als je 'm probeert te debugprinten.... :X

Ik snap dat het lastig is als je een datum uit meerdere niet-geheel-onafhankelijke componenten wil opbouwen, maar op deze manier een partiële state opbouwen is wel een van de slechts denkbare oplossingen. Eigenlijk zou je in één call meerdere velden moeten kunnen meegeven die de datum updaten. Min of meer wat met mktime() al dertig jaar kan.

Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 12:49

Sebazzz

3dp

Soultaker schreef op dinsdag 26 oktober 2010 @ 23:28:
Dit kan wat mij betreft direct door naar het slechte programmeervoorbeeldentopic. Nee, niet vanwege Standeman's code, maar vanwege de klasse die z'n interne representatie wijzigt als je 'm probeert te debugprinten.... :X
Implements quantum dus? Zodra je ernaar kijkt dan wijzigt de data :+

[ Voor 5% gewijzigd door Sebazzz op 27-10-2010 08:28 ]

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

Anoniem: 164019

Heet dat niet een Heisenbug?

Acties:
  • 0 Henk 'm!

  • terje7601
  • Registratie: September 2009
  • Laatst online: 08-02-2024
Het zou me verbazen als JSR-310 niet in Java 8 komt. De nieuwe API is trouwens volledig van scratch geschreven, hoewel hij door dezelfde persoon ontwikkeld wordt als Joda-Time (lees hier waarom).

De huidige Date & Calendar classes zijn inderdaad dringend aan vervanging toe, maar zoals Remus al aangaf is het gebruik ervan gewoon duidelijk gedocumenteerd in de javadoc.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01-07 14:32
Sebazzz schreef op woensdag 27 oktober 2010 @ 08:28:
Implements quantum dus? Zodra je ernaar kijkt dan wijzigt de data :+
+1 Grappig, maar eigenlijk is 't om te huilen natuurlijk. :+
terje7601 schreef op woensdag 27 oktober 2010 @ 09:23:
Het zou me verbazen als JSR-310 niet in Java 8 komt.
Ik ben bang dat de Java ontwikkeling sowieso stagneert nu Sun niet meer bestaat en een groot aantal ontwikkelaars aan 't vertrekken zijn.
Pagina: 1