Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453

    [Java] come fare questa cosa senza millemila IF?

    ciao ragazzi,

    mi sto impappinando con un problema abbastanza semplice, e vorrei chiedervi se a mente fresca vi vengono in mente soluzioni più pulite di quelle che sto provando..

    in un database ho memorizzate una serie di fasce orarie, immaginate una colonna "inizio" ed una colonna "fine", in cui sono memorizzati orari nel formato:

    codice:
    inizio | fine
    --------------
    20:30  | 5:00   
    5:00   | 16:00
    16:00  | 20:30
    Tramite un oggetto calendar recupero l'ora corrente nello stesso formato, e scorrendo le varie righe devo capire in quale fascia oraria è compresa l'ora corrente.

    Ho provato in vari modi facendo (in maniera poco elegante) diversi IF, ma mi salta sempre fuori qualche bug... ad esempio basandomi su confronti, il fatto che le fasce possano essere a cavallo della mezzanotte mi frega, perchè ad esempio l'orario 21:00 non viene riconosciuto come appartentente alla fascia 20:30 - 5:00, perchè è vero che 20 < 21, ma non è vero che 5 > 21 (questo criterio andrebbe bene invece se le fasce non potessero essere mai a cavallo della mezzanotte). Potrei aggiungere altri confronti (tipo andare a vedere se l'ora corrente è dopo la mezzanotte o meno, idem per il limite superiore, e tener di conto di ciò, ma diventa noioso, sporco e poco comprensibile).

    Vi vengono in mente idee più semplici e pulite per fare questa cosa, magari ricorrendo a qualche utilità del linguaggio?

    Grazie!

  2. #2
    Direi che puoi facilitarti molto la vita delegando il lavoro a GregorianCalendar:

    Codice PHP:
    package test;

    import java.util.Calendar;
    import java.util.GregorianCalendar;

    public class 
    Main
    {
       private static 
    String format(GregorianCalendar time)
       {
          return 
    time.get(Calendar.HOUR_OF_DAY) + ":" time.get(Calendar.MINUTE);
       }
       
       public static 
    void main(String[] args)
       {
          
    int hh1 20;              //
          
    int mm1 30;              // 20:30
          
    int hh2 hh1 5+24 5//
          
    int mm2 0;               // 05:00 
          
    int hh3 23;              //
          
    int mm3 10;              // 23:10
       
          
    GregorianCalendar inizio = new GregorianCalendar(0,0,0hh1mm1);
          
    GregorianCalendar fine = new GregorianCalendar(0,0,0hh2mm2);
          
    GregorianCalendar ora = new GregorianCalendar(0,0,0hh3mm3);
          
          
    boolean result ora.after(inizio) && ora.before(fine);     
          
          
    System.out.println(format(inizio) + " <= " format(ora) + " <= " format(fine) + "   =>   " result);
       }

    Ti rimane solo da controllare se controlla le varie casistiche


  3. #3
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453
    ciao, grazie per la risposta...

    purtroppo non basta: prova a sostituire 2:30 invece di 23:30... qui non si accorge che anche 2:30 > 23:30... stavo pensando quando dovremmo sommare 24 all'ora corrente per coprire questo caso..

    EDIT: per ora ho risolto in una maniera alquanto brutta che sembra però funzionare... non sapendo trovare la regolarità riguardo all'aggiungere 24 all'ora corrente per far quadrare le cose in circostanze come quella che ho scritto su, ho detto: visto che le fasce orarie coprono tutto il giorno, se le scorro tutte e non trovo corrispondenza, vuol dire che all'ora corrente va aggiunto 24... e sembra che funzioni. Probabilmente ci sono casi in cui non funzionerà, ma ora non me ne vengono in mente.. Continuiamo comunque a pensare a qualcosa di meno orrendo

    è un problema un po' insidioso pur nella sua semplicità, è difficile avere in mente tutte le possibili combinazioni <definizione delle fasce orarie, orario>...

  4. #4
    Originariamente inviato da Kilin
    ciao, grazie per la risposta...

    purtroppo non basta: prova a sostituire 2:30 invece di 23:30... qui non si accorge che anche 2:30 > 23:30... stavo pensando quando dovremmo sommare 24 all'ora corrente per coprire questo caso..
    Una curiosità. E se hai:

    02:30 del 04/07/10
    20:30 del 04/07/10
    05:00 del 05/07/10 (glielo forziamo noi aggiungendo +24)

    che fai? Tu dici che non funziona però secondo me non hai posto bene il problema. Le 02.30 del giorno indicato NON sono nella fascia oraria specificata.
    Senza indicare il giorno la situazione è ambigua quindi devi forzare un comportamento.

    Cosa scegli di fare in questi casi?

    edit: Per risparmiare tempo, ti ho aggiunto l'altro if per fare esattamente quello che dici tu
    (20:30 <= 02:30 <= 05:00 = true in pratica). In più ti ho creato un metodo che logga i test, così puoi guardare se, in generale, fa quello che deve. Altre casistiche non ne vedo, però non si sa mai.
    Codice PHP:
    package test

    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Calendar
    import java.util.GregorianCalendar
    import java.util.Random;

    public class 
    Main 

       private static 
    String format(GregorianCalendar time
       { 
          
    String hh String.valueOf(time.get(Calendar.HOUR_OF_DAY));      
          
    String mm String.valueOf(time.get(Calendar.MINUTE));
          if(
    hh.length() == 1hh "0" hh;
          if(
    mm.length() == 1mm "0" mm;
          
          return 
    hh ":" mm
       }
       
       private static 
    String format(boolean b)
       {
          if(
    b) return  " true";
          return 
    "false";
       }
        
       private static 
    void log(GregorianCalendar inizioGregorianCalendar fineGregorianCalendar ora
          
    throws IOException
       
    {
          
    File logFile = new File("log.txt");      
          
    FileWriter fw = new FileWriter(logFiletrue);
          
    String out format(inizio) + " <= " format(ora) + " <= " format(fine) + "\t\t= " format((ora.after(inizio) && ora.before(fine)));
          
    fw.write(out "\n");
          
    System.out.println(out);
          
          
    fw.flush();
          
    fw.close();
       }
       
       private static 
    void test() throws IOException
       
    {
          
    Random r = new Random();
          
          for(
    int i 0100i++)
          {
             
    int hh1 r.nextInt(24);
             
    int hh2 r.nextInt(24);
             
    int hh3 r.nextInt(24);
             
    hh3 = (hh3 hh1 && hh3 hh2)? hh3+24hh3;
             
    hh2 hh1 hh2 hh2+24 hh2;
             
             
    GregorianCalendar inizio = new GregorianCalendar(0,0,0hh1r.nextInt(60));                
             
    GregorianCalendar fine = new GregorianCalendar(0,0,0hh2r.nextInt(60)); 
             
    GregorianCalendar ora = new GregorianCalendar(0,0,0hh3r.nextInt(60));
             
    log(iniziofineora);
          }    
       }
       
       public static 
    void main(String[] args)
          
    throws IOException
       

          
    int hh1 20;
          
    int hh2 5;
          
    int hh3 2;
          
    hh3 = (hh3 hh1 && hh3 hh2)? hh3+24hh3;
          
    hh2 hh1 hh2 hh2+24 hh2;           
            
          
    GregorianCalendar inizio = new GregorianCalendar(0,0,0hh130);                
          
    GregorianCalendar fine = new GregorianCalendar(0,0,0hh20); 
          
    GregorianCalendar ora = new GregorianCalendar(0,0,0hh330);  
          
    String out format(inizio) + " <= " format(ora) + " <= " format(fine) + "\t\t= " format((ora.after(inizio) && ora.before(fine)));
          
    System.out.println(out);
          
          
    test();
       } 


  5. #5
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453
    Una curiosità. E se hai:

    02:30 del 04/07/10
    20:30 del 04/07/10
    05:00 del 05/07/10 (glielo forziamo noi aggiungendo +24)

    che fai? Tu dici che non funziona però secondo me non hai posto bene il problema. Le 02.30 del giorno indicato NON sono nella fascia oraria specificata.
    in realtà il giorno non va inteso in questo senso...l'utente immette le fasce orarie avendo in mente che tra le 20:30 e le 05:00 di TUTTI i giorni si deve fare una certa cosa. La fascia oraria non si riferisce ad un certo giorno, ma a tutti i giorni. Quindi la fascia 20:30-05:00 copre sia quegli orari a cavallo tra il 04/07 e il 05/07, sia a quelli a cavallo tra 03/07 e 04/07, perciò le 02:30 dello 04/07 devono esser riconosciute, così come le 02:30 dello 03/07, dello 02/07, ecc.

    Sembra che il tuo programma (molto bellino e utile per testare ) funzioni bene... ora vado a pranzo, dopo cerco di capire ammodino che confronti hai fatto..

    grazie mille per il tuo aiuto, apprezzo davvero molto!

  6. #6
    Originariamente inviato da Kilin
    in realtà il giorno non va inteso in questo senso...l'utente immette le fasce orarie avendo in mente che tra le 20:30 e le 05:00 di TUTTI i giorni si deve fare una certa cosa. La fascia oraria non si riferisce ad un certo giorno, ma a tutti i giorni. Quindi la fascia 20:30-05:00 copre sia quegli orari a cavallo tra il 04/07 e il 05/07, sia a quelli a cavallo tra 03/07 e 04/07, perciò le 02:30 dello 04/07 devono esser riconosciute, così come le 02:30 dello 03/07, dello 02/07, ecc.
    Allora siamo a cavallo. Credo che con l'esempio che ti ho postato possa cavartela abbastanza bene

    [QUOTE
    grazie mille per il tuo aiuto, apprezzo davvero molto! [/QUOTE]

    Figurati!

  7. #7
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453
    Uhm uhm

    Il confronto che hai aggiunto, tradotto in modo che sia più comprensibile estrapolato dal contesto, è:

    codice:
    hAdesso = (hAdesso < hInizio && hAdesso < hFine)? hAdesso+24: hAdesso;
    Però non mi torna tanto... esempio: fascia 16:00 - 18:00, sono le 13:00. 13 < 16, e 13 < 18, perciò aggiunge 24, ma non deve mica...

    forse il test dovrebbe essere hAdesso < hInizio && hAdesso < hFine && hInizio < hFine?


    altro dubbietto, sempre sul tempo: per ottenere l'ora corrente ho fatto
    codice:
    Calendar now = Calendar.getInstance();
            now.set(Calendar.HOUR_OF_DAY, (now.get(Calendar.HOUR_OF_DAY)+2));
    senza la seconda riga infatti l'ora restituita è indietro di due ore.. come mai? c'è un modo meno brutale di risolvere?

  8. #8
    Originariamente inviato da Kilin
    Uhm uhm

    Il confronto che hai aggiunto, tradotto in modo che sia più comprensibile estrapolato dal contesto, è:

    codice:
    hAdesso = (hAdesso < hInizio && hAdesso < hFine)? hAdesso+24: hAdesso;
    Però non mi torna tanto... esempio: fascia 16:00 - 18:00, sono le 13:00. 13 < 16, e 13 < 18, perciò aggiunge 24, ma non deve mica...

    forse il test dovrebbe essere hAdesso < hInizio && hAdesso < hFine && hInizio < hFine?
    vero, devi aggiungere hInzio > hFine (il caso in cui l'ora 'fine' sia nel giorno dopo).


    altro dubbietto, sempre sul tempo: per ottenere l'ora corrente ho fatto
    codice:
    Calendar now = Calendar.getInstance();
            now.set(Calendar.HOUR_OF_DAY, (now.get(Calendar.HOUR_OF_DAY)+2));
    senza la seconda riga infatti l'ora restituita è indietro di due ore.. come mai? c'è un modo meno brutale di risolvere?
    Prova ad utilizzare uno di questi

    codice:
    public static Calendar getInstance(TimeZone zone)
    public static Calendar getInstance(Locale aLocale)

  9. #9
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: [Java] come fare questa cosa senza millemila IF?

    Originariamente inviato da Kilin
    Vi vengono in mente idee più semplici e pulite per fare questa cosa, magari ricorrendo a qualche utilità del linguaggio?
    Basta solo ragionare bene in termini di programmazione ad "oggetti" ... non necessariamente partire in quarta e "fiondarsi" solo su GregorianCalendar.

    - Una classe es. Orario che modella ore/minuti, con i costruttori/metodi sensati. Ad esempio un costruttore senza argomenti per l'ora corrente e uno con ore/minuti. I soliti metodi "getter" e un compareTo(Orario altroOrario) per comparare 2 Orario nel modo più logico e sensato (e qui non centra la logica di comparazione nel range descritta nella discussione).

    - Una classe es. IntervalloOrario che modella due orari di inizio/fine, anche qui con i costruttori/metodi che si può ben immaginare. E con un metodo es. boolean contieneOrario(Orario orario) il cui significato è proprio quello di verificare se un Orario "cade" nel range con la logica particolare descritta.

    Ma diventa banale, anche grazie al compareTo() di Orario:

    A) se orarioInizio <= orarioFine allora un orarioX è contenuto solo se:

    orarioInizio <= orarioX AND orarioX <= orarioFine.

    E qui non c'è nulla di strano, lineare.

    B) se orarioInizio > orarioFine, si usa la logica speciale supponendo che orarioFine è come se fosse dal giorno dopo. Un orarioX è contenuto solo se:

    orarioInizio <= OrarioX AND OrarioX <= Orario(23, 59)
    OR
    Orario(0, 0) <= orarioX AND orarioX <= orarioFine

    Se poi Orario è stato fatto per poter essere costruito solo con orari validi, allora il tutto si potrebbe ridurre a:

    orarioInizio <= orarioX OR orarioX <= orarioFine

    Cosa si nota rispetto alla prima espressione in A)? Che cambia solo una OR invece di una AND!


    Tutto qua.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  10. #10
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453
    Grazie del suggerimento andbin... ragionare come dici è lineare e pulito, però è anche vero che prima di scrivere una classe non fa male vedere se per caso il linguaggio offre quello che fa al caso tuo

    Originariamente inviato da antotan
    vero, devi aggiungere hInzio > hFine (il caso in cui l'ora 'fine' sia nel giorno dopo).




    Prova ad utilizzare uno di questi

    codice:
    public static Calendar getInstance(TimeZone zone)
    public static Calendar getInstance(Locale aLocale)
    Alla fine questa soluzione funziona, e l'ho tenuta, però ho notato che va in crisi quando l'orario corrente coincide perfettamente con un dei limiti della fascia...

    ad esempio sono le 8:00, e la fascia è 8:00-19:00. Credo per via di questa riga, che da false se un orario coincide con inizio o con fine:

    codice:
    adesso.after(inizio) && adesso.before(fine
    credo siano equivalenti a un maggiore e un minore stretto, invece a me servirebbe un maggiore o uguale e un minore o uguale!

    Che dite?

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.