GregorianCalendar, Schaltjahr fehler

  • 10 Antworten
  • Letztes Antwortdatum
H

Heppy1985

Neues Mitglied
0
Einen Wunderschönen wünsche ich,
habe da mal ein Problem mit dem GregorianCalendar und den Schaltjahren:
Ich habe ein Listview mit hilfe des GregorianCalendar und der Funktion getActualMaximum(Calendar.DATE) gefüllt, damit ich immer so viele Einträge in der liste habe wie der aktuelle Monat tage hat. Was zuerst auch wunderbar funktioniert hat, zb der 02.2015 hat 28 tage.
Dan habe ich mit set(Calendar.MONTH, monat-1); den Monat über einen Button reduziert und die liste neu ausgegeben.
Klappte auch wunderbar aber immer wenn ich so in das Jahr 2014 komme und dann wieder über einen anderen Button wieder hoch Zähle zum Februar hat der 02.2015 auf einmal nicht mehr 28 sondern 29 Tage :(
 

Anhänge

  • app4.jpg
    app4.jpg
    57,9 KB · Aufrufe: 232
  • app5.jpg
    app5.jpg
    58 KB · Aufrufe: 218
Woran kann das liegen?
hier mein Adapter zum füllen der liste:
Javascript:
package de.rudolf_heppner.dermanager.berichte;

import android.app.Activity;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;

import de.rudolf_heppner.dermanager.R;
import de.rudolf_heppner.dermanager.db_Helfer;
import de.rudolf_heppner.dermanager.kundenverwaltung.kv_kunden_auswaehlen;
import de.rudolf_heppner.dermanager.stundenlogger.StundenLogger;
import de.rudolf_heppner.dermanager.stundenlogger.ZeitAbfragen;
import de.rudolf_heppner.dermanager.stundenlogger.sl_bericht;

import static de.rudolf_heppner.dermanager.stundenlogger.Konstanten.SL_SPALTE_AZ_ANFANG;
import static de.rudolf_heppner.dermanager.stundenlogger.Konstanten.SL_SPALTE_AZ_ENDE;
import static de.rudolf_heppner.dermanager.stundenlogger.Konstanten.SL_SPALTE_AZ_UNTERSCHIED;
import static de.rudolf_heppner.dermanager.stundenlogger.Konstanten.SL_SPALTE_BERICHT;
import static de.rudolf_heppner.dermanager.stundenlogger.Konstanten.SL_SPALTE_KUNDE;

/**
* Created by Heppy on 16.07.2015.
*/
public class be_monat_stunden_lv_adapter extends BaseAdapter {
    public HashMap<Integer, Integer> list;
    public db_Helfer dbHelfer = null;

    Activity activity;

    String abfrageMonat;
    public be_monat_stunden_lv_adapter(Activity activity, HashMap<Integer, Integer> list, String abfrageMonat) {
        super();
        this.activity = activity;
        this.list = list;
        this.abfrageMonat = abfrageMonat;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public String getdb_ID(int position) {
        return db_Helfer.stunden_spalten_ids.get(position).toString();
    }

    static class ViewHolder {
        TextView datum;
        TextView stunden;
    }

    @Override
    public View getView(final int position, View convertView, final ViewGroup parent) {
        View view = null;
        final  ViewHolder holder; // Erstellt eine ViewHolder Reference
        LayoutInflater inflater = activity.getLayoutInflater();
        final String aktuellerTag;
        if(position < 9) {
            aktuellerTag = "0" + (position+1);
        } else {
            aktuellerTag = "" + (position+1);
        }

        if (convertView == null){
            convertView = inflater.inflate(R.layout.be_monat_stunden_liste, null);
            holder = new ViewHolder();
            holder.datum = (TextView) convertView.findViewById(R.id.be_monats_stunden_liste_spalte_datum);
            holder.stunden = (TextView) convertView.findViewById(R.id.be_monats_stunden_liste_spalte_stunden);

            holder.datum.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    StundenLogger.restart(activity, aktuellerTag+"."+abfrageMonat);
                }
            });
        }
        else {
            // the getTag retuns the viewHolder object set as a tag to the view
            holder = (ViewHolder) convertView.getTag();
        }
        if(holder.stunden != null) {
            holder.stunden.setText("Stunden: " + list.get(position+1));
        }
        if (holder.datum != null) {
            holder.datum.setText(aktuellerTag+"."+abfrageMonat);
        }
        //txtDatum.setText(aktuellerTag+"."+abfrageMonat);
        //txtStunden.setText("Stunden: "+list.get(position+1));

        return convertView;
    }

}
 
Ich glaube ohne den Code, wo du den Kalender manipulierst, wird dir keiner helfen können. Ich vermute jedoch, dass du nur den Monat (und nicht das Jahr) zurück setzt und beim Hochschalten dann beim Februar 2016 landest.
 
ich dachte eigentlich das ich oben ja gesagt hatte womit ich den Kalender manipuliere (sorry wenn das nicht ausreichte) aber hier noch mal ausführlicher:
Javascript:
public void setMonat(int monat) {
        kalender.set(Calendar.MONTH, monat-1);
        aktuellerMonat = kalender.get(Calendar.MONTH)+1;
    }
    public void setJahr(int jahr) {
        kalender.set(Calendar.YEAR, jahr);
        aktuellesJahr = kalender.get(Calendar.YEAR);
    }
public int getAktuellesJahr() {
        return aktuellesJahr;
    }
    public int getAktuellenMonat() {
        return aktuellerMonat;
    }
und hier die onclick für die beien Buttons:
Code:
public void onClick(View v) {
        switch (v.getId()) {
            case R.id.be_monat_zurueck:
                if (kalender.getAktuellenMonat() == 1) {
                    kalender.setJahr(kalender.getAktuellesJahr()-1);
                }
                kalender.setMonat(kalender.getAktuellenMonat() - 1);
                restart(this, kalender.getAktuellenMonatString() + "." + kalender.getAktuellesJahrString());
                break;
            case R.id.be_monat_vor:
                if (kalender.getAktuellenMonat() == 12) {
                    kalender.setJahr(kalender.getAktuellesJahr()+1);
                }
                kalender.setMonat(kalender.getAktuellenMonat()+1);
                restart(this, kalender.getAktuellenMonatString() + "." + kalender.getAktuellesJahrString());
                break;
        }
    }

Und hier noch die Restart Funktion (vielleicht liegtes ja auch daran):

Javascript:
public void restart(Activity activity, String datum) {
        Intent refresh = new Intent(activity, be_monat_stunden.class);
        refresh.putExtra(activity.getString(R.string.bericht_anderes_datum), datum);
        activity.startActivity(refresh);
        activity.finish();
    }
 
wäre es möglich das es am holder liegt????
hab festgestellt das beim scrollen die positionsnummern die bei onCklick übergeben werden geändert werden :
die neu ins bild gescrollten Elemente erhalten die positions nummer der aus dem bild heraus gescrollten elemente
 
Möchtet ihr mal ein Mind Blow haben in Bezug auf dieses Thema? -->
 
  • Danke
Reaktionen: Miss Montage
Warum eigentlich so kompliziert? Warum nutzt du nicht einfach die add()-Methode?

Dein Problem ist, dass du zwar beim Jahreswechsel daran denkst, das Jahr zu verändern, aber den Monat beibehältst. Dadurch laufen die tatsächlichen Daten und das, was du in aktuellerMonat und aktuellesJahr speicherst auseinander.

Beispiel: Dein Datum steht auf 1.1.2015. Du drückst den Button zurück.
So sieht in etwa der wirklich ausgeführte Code aus:
if (kalender.getAktuellenMonat() == 1) { // ist erfüllt
kalender.setJahr(kalender.getAktuellesJahr()-1); -> setJahr(2015-1) // kalender steht hier nach auf 01.01.2014, aktuellesJahr ist auch 2014
}
kalender.setMonat(kalender.getAktuellenMonat() - 1); -> setMonat(1 - 1);
-> kalender.set(Calendar.MONTH, monat-1); // also kalender.set(Calendar.MONTH, -1); ... kalendar steht hier nach auf 01.12.2013, aktuelles Jahr ist aber noch 2014!
-> aktuellerMonat = kalender.get(Calendar.MONTH)+1; -> aktuellerMonat = 11+1 = 12

Beim nächsten Button das gleiche und neben der Erhöhung des Jahres, setzt du dann über die Änderung des Monats kalender direkt über ein Jahr in die Zukunft, womit du bei 2016 landest, was ein Schaltjahr sein wird.


Also nochmal ernstgemeinte Frage, wieso nicht einfach die add()-Methode nutzen?
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: Heppy1985
Im Grunde hört sich das logisch an und ich werde den Code auch danach morgen mal umschreiben um zusehen ob es klappt,
jedoch woran ich zu dieser späten stunde etwas haddere ist das du ja sagst das durch meinen Code beim rückwärts zählen das jahr um zwei zurück gesetzt wird einmal dadurch das ich das Jahr um eines zurück setzte und ein weiteres mal dadurch das der Monat quasi das mach wenn er aus dem zulässigen Bereich fällt. also wird aus 2015 anstelle 2014 wie es sein sollte 2013. Wäre ja akzeptabel aber weiter führst du aus das beim hoch zählen das gleich passiert und ich im Jahr 2016 lande und somit in einem Schaltjahr. aber 2013 + 2 sind 2015 also müsste es doch wieder stimmen abgesehen davon das ich aus versehen 2 Jahre vor und zurück gesprungen bin anstelle von einem.

Falls ich da jetzt was grundsätzlich falsch verstanden habe tut es mir leid und bitte abermals um Aufklärung.

Die add Methode wollte ich vorerst nicht nutzen um im späteren verlauf des Programmes das Datum mit dieser Funktion auch auf ein bestimmtes jahr festlegen zu können anstelle es nur eines hoch oder runter laufen zu lassen. Ja okay könnte ne zweite Methode schreiben welche das dann erledigt. Aber im Grunde müsste es ja gleich bleiben ob ich das folge Jahr ausrechne und fest setze, oder den unterschied zwischen den Jahren errechne und diesen dann adde Oder?

War neugierig und hab es doch gleich mal geändert und die Jahres Änderung entfernt und ja er hat immer um 2 Jahre gezählt, zudem ist mir aufgefallen das ich bei der Monat Änderung besser auch das Jahr neu abfrage so damit mein Programm mit dem synchron bleibt. Hattest also recht und ich bin die sehr dankbar für den denk Anstoß wobei ich noch nicht verstehe warum ich denn lieber die add Funktion als die set nehmen soll.
 
Weil man immer die Funktion nehmen sollte, die das was man will am besten kann.
Und wenn du monoton die Monate hochzählen willst ist ein add sehr viel einfacher als die einzelnen Felder per set zu setzen.
Wie du selbst gesehen hast, macht man dabei Fehler. Dein Jahresrechenfehler wird nicht der einzige sein den du einbaust wenn du was komplizierteres verwendest. KISS Prinzip.
 
Heppy1985 schrieb:
Falls ich da jetzt was grundsätzlich falsch verstanden habe tut es mir leid und bitte abermals um Aufklärung.
Fast alles richtig verstanden, nur benutzt du zum Zählen (egal ob runter oder hoch) die Variable aktuellesJahr (bzw. die get-Methode) als Referenz und diese weicht vom tatsächlichen Datum in kalender ab. Und wenn du dann im Dezember (aktuellerMonat = 12) den set ausfürhst, sagst du er soll das Datum auf Tag=01, Monat=aktuellerMonat+1. Jahr = aktuellesJahr+1 setzen (-> Tag=01, Monat=13, Jahr = 2015) => 01.01.2016

Das ist auch noch so ein Punkt, den ich nicht verstehe. Wieso speicherst du das nochmal zwischen? Du könntest in den Methoden getAktuellesJahr und getAktuellenMonat doch auch kalender nutzen, warum doppelt?

Gehe am besten beim Debuggen mal einzeln durch und siehe dir jeweils die Inhalte der Variablen kalender, aktuellesJahr und aktuellerMonat an (notfalls baue entsprechende Ausgaben ins Log ein), dann wird es hoffentlich klarer.

Oh das hat sich ja schon erledigt - naja für die Nachwelt :smile:

Heppy1985 schrieb:
wobei ich noch nicht verstehe warum ich denn lieber die add Funktion als die set nehmen soll.
Keep-It-Simple hat @deek ja schon erwähnt. Du rufst einfach nur kalender.add(Calendar.MONTH, 1) für Monat vor und kalender.add(Calendar.MONTH, -1) für Monat zurück auf. Jahresüberläufe macht dann das Objekt ganz von alleine und du sparst dir die ganzen Sonderwege für die Überläufe. Und wenn du konkret ein Datum setzen möchtest, dann würde ich die set-Methode (die das Objekt ja sowieso schon hat) nutzen -> set(int year, int month, int day).
 
Zuletzt bearbeitet:
Das zwischen speichern hatte ich anfangs deshalb gemacht um eigentlich den Kalender auf dem heutigen Datum zu belassen und nur die variablen zu editieren. Damit ich wenn ich kurzfristig ein anderes aktivity aufrufe nit einen neuen Kalender erzeugen muss. Sondern einfach das Heutige Datum wieder aus diesem Kalender laden kann. Naja der Gedanke hat sich irgendwie verflüchtigt, jetzt stehen die variablen nur noch drin weil ich mir dachte es ist besser eine variable mehrfach in einem activity ab zu fragen als jedes mal den Kalender aus zu lesen.

Was die Jahresüberläufe angeht das macht die set Methode das Objektes auch selbst, das hab ich anfangs nur nicht mitbekommen da ich ja diesen Fehler mit der Aktualisierung der Jahres variable hatte. Deswegen fügte ich ja noch den Code hinzu der das Jahr fälschlicherweise ein weiteres mal erweiterte. Dies wäre mir aber auch mit der add Methode passiert. daher denke ich werde ich bei der set Methode bleiben da ich sie ja später eh brauchen werde um ein genaues Datum zu setzten. Aber die zwischen Speicherung des Kalenders werde ich wohl entfernen um späteren Problemen aus dem weg zu gehen. Danke euch für die Denkanstöße.
 
Zurück
Oben Unten