Problem mit erster Kalenderwoche

TomAdam

Mitglied
Moin,

ich bin auf folgendes Problem gestossen: Wenn ich für den 31.12.2012 die Kalenderwoche ermitteln möchte, liefert mir der GregorianCalendar trotz gesetzter TimeZone und Locale statt ""01.2013" fälschlich "01.2012" als Ausgabe zurück. Wie komme ich auf den korrekten Wert bzw. was mache ich flscha?

Java:
Calendar calendar = GregorianCalendar.getInstance(
        		TimeZone.getTimeZone( "Europe/Berlin" ), 
        		Locale.GERMANY);        
        calendar.setMinimalDaysInFirstWeek(4);
        SimpleDateFormat df = new SimpleDateFormat("dd.MM.yyyy");        
        try
    	{			
        	calendar.setTime(df.parse("31.12.2012"));
        }
        catch (Exception ignore) {}
        
        df.applyPattern("ww.yyyy");
        System.out.println("Woche/Jahr: " + df.format(calendar.getTime()));

Grüsse


Tom
 
Wie kommst du darauf dass der 31.12.2012 in der ersten KW des Jahres 2013 liegen soll? Btw:
Java:
catch (Exception ignore) {}
Sowas is auch immer ganz toll wenn man irgend einen Fehler hat und den dann sucht....
 
Liegts daran? (4-Tage-Woche?)

Nein, die erste Woche des Jahres ist nach DIN/ISO die Woche, in die mindestens vier Tage des neuen Jahres fallen, dieser Wert wird damit gesetzt bzw. sollte damit eigentlich gesetzt werden.
Wenn man die Zeile auskommentiert, ändert das aber nichts am falschen Ergebnis.


Wie kommst du darauf dass der 31.12.2012 in der ersten KW des Jahres 2013 liegen soll?

Ein Blick auf den neuen Wandkalendar verrät mir das.

Btw:
Java:
catch (Exception ignore) {}
Sowas is auch immer ganz toll wenn man irgend einen Fehler hat und den dann sucht...

Im Beispielcode tritt keine Exception auf. In der Anwendung würde ich allfällige Exceptions natürlich handeln.


Tom
 
ab Java 1.7 scheint es in SimpleDateFormat gerade Y statt y neu zu geben
SimpleDateFormat (Java Platform SE 7 )
kann ich persönlich nicht testen, yyyy selber kann offensichtlich nur das normale richtige Jahr sein

erschaunlicherweise in Calendar keinerlei Angebot, sofern ich das überblicke,
da zweifle ich dann dass SimpleDateFormat mehr kann, aber was soll Y dort als 'Week year' sonst sein?
nach
java - Getting wrong data when using SimpleDateFormat.parse() - Stack Overflow
sieht es auch funktionierend aus

im Zweifel selber zusammenbauen (+1 ..) oder vielleicht bei Alternativen wie Joda Time vorbei schauen

noch ein Link
java - SimpleDateFormat Week Calculations - Stack Overflow
 
yyyy gibt IMMER das Jahr aus, welches vom Calendar angegeben ist. Das Problem mit dem Ausgeben der Woche kannst du lösen, indem du auf den Donnerstag der Woche springst.

Aus dem 31.12.12 wird dann der 03.01.13 und wenn du von dem das Calendar-Objekt mit dem Format ww.yyyy ausgibst, bekommst du das richtige Ergebnis.

[EDIT]Muss natürlich der Donnerstag sein. Denn wenn der Donnerstag einer Woche im alten Jahr liegt, gehört die Woche zum alten Jahr und wenn der Donnerstag der Woche im neuen Jahr liegt, gehört die Woche zum neuen Jahr.[/EDIT]
 
Zuletzt bearbeitet:
Das Problem mit dem Ausgeben der Woche kannst du lösen, indem du auf den Donnerstag der Woche springst.

Danke, aber das löst nicht mein Problem, für ein bestimmtes Datum wie den 31.12.2012 oder den 30.12.2013 die richtige Kalenderwoche zu bestimmen. Das Problem scheint im übrigen nur bei Jahren aufzutreten, die 52 Wochen haben, bei Jahren mit 53 Wochen klappt es problemlos.


Tom
 
> Das Problem scheint im übrigen nur bei Jahren aufzutreten, die 52 Wochen haben, bei Jahren mit 53 Wochen klappt es problemlos.

einfach so klingt der Satz etwas unintelligent, da kann man ruhig weiterdenken 😉
bei 53 Wochen in einem Jahr ist der Definiton nach eine 53. im Jahr angebrochen,
nach der begrenzten Anzahl Tage im Jahr wird diese 53. garantiert bis ins nächste Jahr laufen,
das 'Problem', dass die erste Woche des nächsten Jahres noch ins alte reinreicht, kann es nicht geben

also sieht die natürliche Situation günstig aus, deshalb kommt Java nicht in Verlegenheit, immer noch das Problem zu haben,
wobei es dann übrigens für den Jahresanfang ungünstig aussieht:
für 01.01.2012, nach einem 53er-Jahr 2011, gibt dein Programm '52.2012' aus, auch nicht günstig

ich erlaube mir dieses halbe Offtopic, weil im Thema auch nicht mehr viel zu sagen ist,
hast du YYYY probiert, oder kein Java 1.7?
wenn du mit Calendar die Zahlen einzeln holen würdest, könntest du ja bisschen rechnen:
'wenn Dezember und Woche < 40, dann wohl Jahr+1'

edit:
ok, das Beispiel 2011 gewählt zu haben ist vor mir nicht grad intelligent, da gab es gar keine 53. Woche,
zumal auch Ausgabe '52.2012', der Rest dürfte aber noch stimmen, 2009 etwa
 
Zuletzt bearbeitet von einem Moderator:
einfach so klingt der Satz etwas unintelligent, da kann man ruhig weiterdenken 😉
bei 53 Wochen in einem Jahr ist der Definiton nach eine 53. im Jahr angebrochen,
nach der begrenzten Anzahl Tage im Jahr wird diese 53. garantiert bis ins nächste Jahr laufen,
das 'Problem', dass die erste Woche des nächsten Jahres noch ins alte reinreicht, kann es nicht geben

also sieht die natürliche Situation günstig aus, deshalb kommt Java nicht in Verlegenheit, immer noch das Problem zu haben,
wobei es dann übrigens für den Jahresanfang ungünstig aussieht:
für 01.01.2012, nach einem 53er-Jahr 2011, gibt dein Programm '52.2012' aus, auch nicht günstig

Ja richtig wäre in diesem Fall 52.2011 ansonsten verstehe ich nur Bahnhof.

ich erlaube mir dieses halbe Offtopic, weil im Thema auch nicht mehr viel zu sagen ist,
hast du YYYY probiert, oder kein Java 1.7?

Java 7 ist definitiv keine Option, max. steht Java 6 zur Verfügung.

wenn du mit Calendar die Zahlen einzeln holen würdest, könntest du ja bisschen rechnen:
'wenn Dezember und Woche < 40, dann wohl Jahr+1'

Äh, Dezember UND Woche < 40 ergibt irgendwie immer false.
Na ja, da werde ich mir wohl selbst einen workaround einfallen lassen müssen. Ich dachte, das liesse sich einfach mit den vorhandenen Bordmitteln lösen.


Tom
 
> Äh, Dezember UND Woche < 40 ergibt irgendwie immer false.

31.12.2012 -> Woche 1 und Dezember -> also zum Jahr 2012 +1 -> "01.2013" statt "01.2012", das wolltest du doch
 
Code:
SimpleDateFormat df = new SimpleDateFormat("ww.Y");
funktioniert bei mir zumindest auch mit eingestelltem Java 1.5.

Sonst würde ich immernoch dazu raten das Calendarobjekt auf das Datum des Donnerstags zu setzen.
 
Java:
public static void identifyWeekOfYear() {
     int iWoche;
     Calendar cal = Calendar.getInstance();
     cal.set(2012, 11, 31);
	
     iWoche = cal.get(Calendar.WEEK_OF_YEAR);
     System.out.println(iWoche);
}

Ausgabe: 1

Wo genau liegt da das Problem? Die 'richtigen' Werkzeuge wählen.
 
die Ausgabe 1 funktioniert auch bei SimpleDateFormat im ersten Post, genauer lesen

fraglich ist das Jahr, gewünscht ist 2013 statt 2012,
gewisse Wege sind aber bereits gezeigt
 
Hättest du dir den Thread durchgelesen würdest du merken, dass das Problem nicht die Woche sondern das Jahr ist.
[EDIT]Ups, zu spät 😀[/EDIT]
 
bzzz ersetzt man 2012 durch 2013 ist die Ausgabe immernoch 1, also immernoch richtig

der letzte Beitrag vom TO wirkte auf mich nicht so, als wäre das Problem erledigt
nur weil hier mehrere Wege "angezeigt" wurden heisst doch nicht, dass ich nicht auch einen Weg vorgeben kann?
Die Wege von Slater und Darkscream wirken auf mich wie Workarounds... wenn dann oder Datum auf Do setzen. Daher meine Aussage "richtige Werkzeuge"... wozu der Umweg über SimpleDateFormat wenns mit Calendar schneller, einfacher und vor allem richtig geht? Ich kann einen Nagel auch mit einem Schuh ein'hämmern', praktikabel ist anders.

Naja meine Meinung :/
 
was genau ist denn deine Aussage, deine Meinung?
letztlich kann man immer auf SimpleDateFormat verzichten, jede beliebige Darstellung mit Calendar-Abfragen zusammenbauen,
aber das ist ja wohl nicht logisch, dann gäbe es SimpleDateFormat nicht..

das Ziel ist "01.2003" für 31.12.2012,
wenn es mit SimpleDateFormat möglich wäre, ab Java 1.7 anscheinend "ww.YYYY", dann ein idealer sauberer Schritt,
alles andere mit Calendar.get() oder Datumwechsel vergleichsweise Gefrickel, aber eben nötig

(edit: ui, schon wieder mit D4rkscr43m gleichzeitig 😉 )
 
Sonst würde ich immernoch dazu raten das Calendarobjekt auf das Datum des Donnerstags zu setzen.

Es muss aber mit jedem beliebigen Startdatum richtig funktionieren. Ich habe mir jetzt folgende Lösung erarbeitet. Der Code gibt in einer Schleife die KW für die nächsten 250 Wochen ab einem beliebigen Startdatum heraus.
Java:
	public static void main(String[] args)
	{
		Calendar cal = (GregorianCalendar) Calendar.getInstance(TimeZone.getTimeZone( "Europe/Berlin" ), Locale.GERMANY);         
		SimpleDateFormat df = new SimpleDateFormat("dd.MM.yyyy"); 
		
		try
        {           
            cal.setTime(df.parse("01.01.2012")); // Hier das Startdatum setzen
        }
        catch (Exception ignore) {}		
		
		// Vergleichskalender für das Vorjahr
        Calendar comp = Calendar.getInstance(Locale.GERMANY);        

        for(int weeks = 0; weeks < 250; weeks++) // Beispiel: nächste 250 Wochen
        {  	
        	comp.set(Calendar.YEAR, (cal.get(Calendar.YEAR) - 1));
        	
        	// Fall 1: Jahr mit 52 Wochen, 1. KW beginnt im Dezember
        	if((cal.get(Calendar.MONTH) == Calendar.DECEMBER && cal.get(Calendar.WEEK_OF_YEAR) == 1) && cal.getActualMaximum(Calendar.WEEK_OF_YEAR) == 52)
        	{
        		System.out.println("(1)Woche/Jahr: " + "01." + (cal.get(Calendar.YEAR) + 1));        		
        	}  
        	else
        	{
        		// Fall 2: Jahr mit 53 Wochen, 1. KW beginnt im Januar
        		if(cal.get(Calendar.MONTH) == Calendar.JANUARY 
        				&& cal.get(Calendar.WEEK_OF_YEAR) == 53 
        			 	&& cal.getActualMaximum(Calendar.WEEK_OF_YEAR) == 52 
        			 	&& comp.getActualMaximum(Calendar.WEEK_OF_YEAR) == 53)
        		{
        			System.out.println("(2)Woche/Jahr: " + "53." + (cal.get(Calendar.YEAR) - 1));
        		}        		
        		else
        		{
        			// Fall 3: Jahr mit 52 Wochen, 52. KW geht in den Januar
        			if(cal.get(Calendar.MONTH) == Calendar.JANUARY 
            				&& cal.get(Calendar.WEEK_OF_YEAR) == 52 
            			 	&& cal.getActualMaximum(Calendar.WEEK_OF_YEAR) == 52
            			 	&& comp.getActualMaximum(Calendar.WEEK_OF_YEAR) == 52)
            		{
        				System.out.println("(3)Woche/Jahr: " + "52." + (cal.get(Calendar.YEAR) - 1)); 
            		}
            		
                	else // Fall 4: Der Normalfall
                	{	                		
                		System.out.println("(4)Woche/Jahr: " + new SimpleDateFormat("ww.yyyy").format(cal.getTime()));            			
                	}
        		}        		
        	}    	
        	cal.add(Calendar.WEEK_OF_YEAR, 1);        	
        }
   }

Falls jemandem noch etwas auffällt bin ich für Hinweise dankbar.


Tom
 
Du hast einfach einen Denkfehler beim ursprünglichen Jahr
yyyy gibt dir das Jahr des Datums aus, das gerade im Calendar steht. unabhängig davon was du sonst noch wissen willst.

ww gibt dir die woche aus, unabhängig vom jahr. die werte haben keine verbindung.

also funktionierte schon im ursprünglichen code alles, so wie es gedacht ist


wenn die woche < 10 ist und das datum im dezember liegt, einfach das jahr +1 ausgeben

Hinweis: dein code trägt die Kirche ums Dorf, hier eine vernünftige lösung
Java:
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone( "Europe/Berlin" ), Locale.GERMANY);
        SimpleDateFormat df = new SimpleDateFormat("dd.MM.yyyy");

        try
        {
            cal.setTime(df.parse("01.01.2012")); // Hier das Startdatum setzen
        }
        catch (Exception e) {
            System.out.println(e);
        }

        for(int weeks = 0; weeks < 250; weeks++) // Beispiel: nächste 250 Wochen
        {
            int week = cal.get(Calendar.WEEK_OF_YEAR);
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH);

            year +=  month == Calendar.JANUARY && week > 50 ? -1 : month == Calendar.DECEMBER && week == 1 ? 1 : 0;
            System.out.println(String.format("Woche/Jahr: %02d.%d", Integer.valueOf(week),Integer.valueOf(year)));

            cal.add(Calendar.WEEK_OF_YEAR, 1);
        }
 
Zuletzt bearbeitet von einem Moderator:
das Ziel ist "01.2003" für 31.12.2012,
wenn es mit SimpleDateFormat möglich wäre, ab Java 1.7 anscheinend "ww.YYYY", dann ein idealer sauberer Schritt

Und ich meine, dass ein einzelnes "Y" schon reicht und auch schon vor Java 1.7 funktioniert.

compilr bestätigt mich darin auch.
Java:
java.util.Calendar c = new java.util.GregorianCalendar(2012, 11, 31);
java.text.SimpleDateFormat s = new java.text.SimpleDateFormat("w.Y");
System.out.println(s.format(c.getTime()));
führt auch da zur Ausgabe von
Code:
1.2013
 
Hallo zusammen

Auf der Suche nach einer Lösung für mein Problem, bin ich auf diesen Thread gestossen.

Aus einer Datenbank bekomme ich Jahr und Woche (yyyyww).
Mit dem folgenden Code wird dieser Wert umformatiert:

**********Code aus einem Birt Report**********
dfParser = new Packages.java.text.SimpleDateFormat("yyyyww");
df = new Packages.java.text.SimpleDateFormat("ww-yyyy");
myDate = dfParser.parse(row["val_num"]);
formattedDate = df.format(myDate);
****************************************

Das Ergebnis seht Ihr unten. Irgendwie hängen Woche und Jahr schon zusammen.
Ich verwende auch Java 1.6.

val_num formattedWeek
201247 47-2012
201248 48-2012
201249 49-2012
201250 50-2012
201251 51-2012
201252 52-2012
201301 01-2012

Es hat den Anschein, ob das Jahr in der KW 53/2012 ist, die Woche jedoch schon in KW 01/2013.

Hat jemand eine Erklärung? Ev. Bug im SimpleDateFormat?

Danke und Gruss
Piero
 
dein Programm ist unnötig kompliziert mit Erwähnung der Datenbank + Birt und unnötig unvollständig,
wahrscheinlich meinst du folgendes 100% klares, von jedermann ausführbares vollständiges Programm:
Java:
public class Test2
{
    public static void main(String[] args) throws Exception
    {
        String st = "201301";
        SimpleDateFormat dfParser = new SimpleDateFormat("yyyyww");
        SimpleDateFormat df = new SimpleDateFormat("ww-yyyy");
        Date myDate = dfParser.parse(st);
        System.out.println(myDate);
        System.out.println(df.format(myDate));
    }
}
Ausgabe:
Code:
Mon Dec 31 00:00:00 CET 2012
01-2012

das entspricht weitgehend den vorherigen Problemen, es ist eindeutig ein Datum aus dem Jahr 2012, aber Kalenderwoche 1 aus dem nächsten Jahr,
das Jahr 2012 HAT nunmal keine 53 Wochen
Alle Kalenderwochen 2012, kw kalender 2012 - kalenderwoche.net

würde man '01-2012' wieder parsen, käme man an den Anfang des Jahres 2012, weil nicht erkennbar ist dass die Kalenderwoche des nächsten Jahres gemeint ist,
das ist sicherlich nicht schön, aber was sollte die Alternative sein?
das SimpleDateFormat kann für den Montag der 1. Woche 2013, Silverster vor 4 Tagen, 31.12.2012, doch nicht das Jahr 2013 behaupten, eindeutig ist 2012 richtig,

vielleicht wäre eine generelle Erweiterung nötig, 'gib Kalenderwoche + Kalenderwoche-Jahr' = 01-2013
 
Hallo SlaterB

Wollte mich noch bedanken. Sorry, wenn ich etwas zu wenig präzis war.

Mit Java 1.7 bietet das SimpleDateFormat das Symbol "Y". Hier passen dann Woche und Jahr zusammen.
Übrigens bietet auch ein Package von der IBM diese Möglichkeit (Packages.com.ibm.icu.text).

Viele Grüsse
Piero
 
ach ja, das große Y, kürzlich auch schonmal gelesen und vorgeschlagen
(spätes edit: war ja in diesem Thema, auf Seite 1..)
 
Zuletzt bearbeitet von einem Moderator:

Zurück
Oben