Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2009
    Messaggi
    174

    Anomalia calendario

    Ciao a tutti! Ho un problema con il seguente codice
    codice:
        private static String[] nomiMesi = {"Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"};
        private static String[] nomiGiorni = {"Lun", "Mar", "Mer", "Gio", "Ven", "Sab", "Dom"};
        private GregorianCalendar dataAttuale;
        private int settimana;
        
        /**Questo costruttore crea un'istanza della classe impostando la data del 
         * calendario a quella passata come parametro
         * 
         * @param dataAttuale 
         */
        public Calendario(GregorianCalendar dataAttuale) {
            this.dataAttuale = dataAttuale;
            settimana = dataAttuale.get(Calendar.WEEK_OF_MONTH);
        }
        
        /**Questo costruttore crea un'istanza della classe impostando la data del 
         * calendario a quella corrente
         * 
         */
        public Calendario() {
            GregorianCalendar dataCorrente = new GregorianCalendar(Locale.ITALIAN);
            this.dataAttuale = dataCorrente;
            settimana = dataCorrente.get(Calendar.WEEK_OF_MONTH);
        }
    
    public String stampaCalendario() {
            System.out.println(">>> " + dataAttuale.get(Calendar.DATE) + " " + nomiMesi[dataAttuale.get(Calendar.MONTH)] + " " + dataAttuale.get(Calendar.WEEK_OF_MONTH));
            
            
            String calendario = "";
            
            // stampo il mese e l'anno attuale
            int mese = dataAttuale.get(Calendar.MONTH);
            calendario = calendario.concat(nomiMesi[mese % 12] + " " + dataAttuale.get(Calendar.YEAR) + "\n");
            
            // stampo le intestazioni dei giorni del calendario
            for (int i = 0; i < nomiGiorni.length; i++) {
                calendario = calendario.concat(nomiGiorni[i] + "\t");
            }
            calendario = calendario.concat("\n");
            
            // mi allineo con il nome del primo giorno del mese
            Calendar cal = Calendar.getInstance(Locale.ITALIAN);
            cal.set(dataAttuale.get(Calendar.YEAR), dataAttuale.get(Calendar.MONTH), 0);
            int primoMese = cal.get(Calendar.DAY_OF_WEEK);
            for (int i = 0; i < primoMese-1; i++) {
                calendario = calendario.concat("\t");
            }
            
            // stampo i giorni fino all'ultimo del mese
            int ultimoMese = dataAttuale.getMaximum(Calendar.DAY_OF_MONTH);
            for (int i = 1; i <= ultimoMese; i++) {
                calendario = calendario.concat(i + (i == dataAttuale.get(Calendar.DATE) ? "*" : "") + "\t");
                
                // se domenica torno al primo giorno della settimana 
                if ((i + primoMese) % 7 == Calendar.SUNDAY) {
                    calendario = calendario.concat("\n");
                }
            }
            calendario = calendario.concat("\n");
            
            return "";//calendario;
        }
    In pratica dovrei stampare un calendario nel quale evidenziare la settimana corrente, ma in alcuni mesi come settembre, novembre e dicembre del 2011 tutto funziona correttamente, mentre ad esempio con ottobre prossimo la settimana risulta sfalsata di 1.
    Sapreste dirmi il motivo dell'anomalia?
    Grazie infinite.

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Ci sono diverse di imprecisioni.

    codice:
    int mese = dataAttuale.get(Calendar.MONTH);
    calendario = calendario.concat(nomiMesi[mese % 12] + " " + dataAttuale.get(Calendar.YEAR) + "\n");
    la parte in grassetto è perfettamente inutile. Il mese restituito dal get(Calendar.MONTH) è sempre un numero compreso fra 0 (gennaio) e 11 (dicembre), come da specifica.

    codice:
    // mi allineo con il nome del primo giorno del mese
    Calendar cal = Calendar.getInstance(Locale.ITALIAN);
    cal.set(dataAttuale.get(Calendar.YEAR), dataAttuale.get(Calendar.MONTH), 0);
    La parte in grassetto è sbagliata: il primo giorno del mese è sempre 1, non 0.

    Poi il resto non l'ho guardato, perchè già qui la logica si perde completamente.

    PS: Conviene usare un oggetto StringBuilder (o StringBuffer) quando devi effettuare diverse concatenazioni di stringhe, in modo da rendere più efficiente il codice.

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2009
    Messaggi
    174
    ok, forse il codice è un pò incasinato. Grazie comunque per la risposta. posto una versione più semplificata.
    codice:
    package calendario;
    
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    import java.util.Locale;
    
    public class Calendario {
    
      private static String[] nomiMesi = {"Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"};
      private GregorianCalendar dataAttuale;
    
      /**Questo costruttore crea un'istanza della classe impostando la data del 
       * calendario a quella corrente
       * 
       */
      public Calendario() {
          GregorianCalendar dataCorrente = new GregorianCalendar(Locale.ITALIAN);
          this.dataAttuale = dataCorrente;
      }
      
      /**Questo costruttore crea un'istanza della classe impostando la data del 
       * calendario a quella passata come parametro
       * 
       * @param dataAttuale 
       */
      public Calendario(GregorianCalendar dataAttuale) {
          this.dataAttuale = dataAttuale;
      }
      
      /**Questo metodo ritorna un intero corrispondente alla settimana alla quale
       * appartiene la data attuale
       *
       */
      public int getSettimanaAttuale() {
        return dataAttuale.get(Calendar.WEEK_OF_MONTH);
      }
      
      /**Questo metodo fa avanzare la data attuale al mese successivo
       *
       */
      public void aggiungiMese() {
        dataAttuale.add(Calendar.MONTH, 1);
      }
      
      /**Questo metodo restituisce la data attuale
       *
       */
      public Calendar getDataAttuale() {
        return dataAttuale;
      }
      
      /**Questo metodo restituisce una stringa con le informazioni sulla settimana
       * 
       * @return 
       */
      public String stampaInfoSettimana() {
          return dataAttuale.get(Calendar.DATE) + " " + nomiMesi[dataAttuale.get(Calendar.MONTH)] + " --> " + dataAttuale.get(Calendar.WEEK_OF_MONTH);
      }
    }
    ed ecco un main
    codice:
    package calendario;
    
    public class Main {
    
        public static void main(String[] args) {
    
            Calendario c = new Calendario();
    
            for (int i = 0; i < 12; i++) {
                System.out.println(c.stampaInfoSettimana());
                c.aggiungiMese();
            }
        }
    }
    spero che adesso sia più chiaro.
    Grazie

  4. #4
    Utente di HTML.it
    Registrato dal
    Mar 2009
    Messaggi
    174
    In pratica l'anomalia consiste nel fatto che se il giorno nel mese capita di venerdì, sabato o domenica allora mi dice che la settimana è quella precendente. Inizialmente pensavo potesse essere un problema di localizzazione e invece no.

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Non ho capito la problematica. A me il calcolo del numero di settimana (fornito dalla classe GregorianCalendar) funziona tranquillamente.

    codice:
    import java.util.*;
    
    public class Settimana {
       public static void main(String[] args) {
          GregorianCalendar gc = new GregorianCalendar(2011, 8, 1);
          for(int i=0; i<15; i++) {
             System.out.println( gc.get(Calendar.WEEK_OF_MONTH) );
             gc.add(Calendar.DATE, 1);
          }
       }
    }
    Questo codice stampa il numero di settimana dei primi 15 giorni di Settembre (il primo giorno è un giovedì).

    Output:
    codice:
    1
    1
    1
    1
    2
    2
    2
    2
    2
    2
    2
    3
    3
    3
    3
    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Utente di HTML.it
    Registrato dal
    Mar 2009
    Messaggi
    174
    E cosa c'è di sbagliato in questo codice visto che non va?
    codice:
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    
    public class Main {
    
        public static void main(String[] args) {
    
            GregorianCalendar gc = new GregorianCalendar();
            for (int i = 1; i < gc.getMaximum(Calendar.DAY_OF_MONTH); i++) {
                System.out.println("Giorno " + i + "/" + (gc.get(Calendar.MONTH)+1) + " " + gc.get(Calendar.WEEK_OF_MONTH));
                gc.add(Calendar.DATE, 1);
            }
        }
    }
    l'output è questo
    codice:
    Giorno 1/9 2
    Giorno 2/9 2
    Giorno 3/9 2
    Giorno 4/9 3
    Giorno 5/9 3
    Giorno 6/9 3
    Giorno 7/9 3
    Giorno 8/9 3
    Giorno 9/9 3
    Giorno 10/9 3
    Giorno 11/9 4
    Giorno 12/9 4
    Giorno 13/9 4
    Giorno 14/9 4
    Giorno 15/9 4
    Giorno 16/9 4
    Giorno 17/9 4
    Giorno 18/9 5
    ...
    non mi sembra sia corretto

  7. #7
    Utente di HTML.it
    Registrato dal
    Mar 2009
    Messaggi
    174
    ok, ho capito, come non detto...

  8. #8
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Spieghiamolo anche agli altri.

    Questa linea di codice
    codice:
    GregorianCalendar gc = new GregorianCalendar();
    Crea un oggetto Calendar posizionato alla data e ora attuali.

    Poi tu, con un ciclo for, fai stampare il valore della variabile "i" (che parte da 1), seguito dal valore del mese attuale (recuperato dal Calendar)... questo fa sì che vengano stampati i giorni del mese dal primo all'ultimo... ma al Calendar non stai dicendo nulla... quindi lui è sempre posizionato alla data attuale (e non al primo giorno del mese!!). Quindi, se quel codice l'hai fatto eseguire il giorno del post (9/9), il Calendar era posizionato effettivamente nella seconda settimana del mese... poi tu gli aggiungi un giorno per ogni cilo e lui va avanti...

    In buona sostanza, il Calendar non ti dava le informazioni relative al "giorno costruito" che tu stavi stampando... ma le informazioni relative alle operazioni effettuate a partire dalla data di esecuzione.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.