Domanda

Sto lavorando a un progetto in cui il requisito è che la data venga calcolata come l'ultimo venerdì di un determinato mese.Penso di avere una soluzione che utilizza solo Java standard, ma mi chiedevo se qualcuno sapesse qualcosa di più conciso o efficiente.Di seguito è riportato ciò che ho testato quest'anno:

    for (int month = 0; month < 13; month++) {
        GregorianCalendar d = new GregorianCalendar();
        d.set(d.MONTH, month);
        System.out.println("Last Week of Month in " + d.getDisplayName(d.MONTH, Calendar.LONG, Locale.ENGLISH) + ": " + d.getLeastMaximum(d.WEEK_OF_MONTH));
        d.set(d.DAY_OF_WEEK, d.FRIDAY);
        d.set(d.WEEK_OF_MONTH, d.getActualMaximum(d.WEEK_OF_MONTH));
        while (d.get(d.MONTH) > month || d.get(d.MONTH) < month) {
            d.add(d.WEEK_OF_MONTH, -1);
        }
        Date dt = d.getTime();
        System.out.println("Last Friday of Last Week in  " + d.getDisplayName(d.MONTH, Calendar.LONG, Locale.ENGLISH) + ": " + dt.toString());
    }
È stato utile?

Soluzione

Basato su contrassegnato 23 suggerimento:

public Date getLastFriday( int month, int year ) {
   Calendar cal = Calendar.getInstance();
   cal.set( year, month + 1, 1 );
   cal.add( Calendar.DAY_OF_MONTH, -( cal.get( Calendar.DAY_OF_WEEK ) % 7 + 1 ) );
   return cal.getTime();
}

Altri suggerimenti

Lascia che Calendar.class faccia la sua magia per te ;)

pCal.set(GregorianCalendar.DAY_OF_WEEK,Calendar.FRIDAY);
pCal.set(GregorianCalendar.DAY_OF_WEEK_IN_MONTH, -1);

Non è mai necessario eseguire il loop per scoprirlo.Per determinare la data dell'"ultimo venerdì" per questo mese, iniziare con il primo giorno del mese successivo.Sottrai il numero appropriato di giorni a seconda del giorno (numerico) della settimana in cui cade il primo giorno del mese.C'è il tuo "venerdì scorso". Sono abbastanza sicuro che possa essere ridotto a un longish di un liner, ma non sono un Dev Java.Quindi lo lascerò a qualcun altro.

java.time

Utilizzando java.time libreria integrata in Java 8 e versioni successive, è possibile utilizzare TemporalAdjusters.lastInMonth:

val now = LocalDate.now() 
val lastInMonth = now.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY))

Puoi scegliere qualsiasi giorno dal DayOfWeek enum.

Se è necessario aggiungere informazioni sull'orario, è possibile utilizzare quelle disponibili LocalDate A LocalDateTime conversione come

lastFriday.atStartOfDay() // e.g. 2015-11-27T00:00

Vorrei usare una libreria come Jodatime.Ha un'API molto utile e utilizza i normali numeri dei mesi.E soprattutto, è thread-safe.

Penso che tu possa avere una soluzione con (ma forse non la più breve, ma sicuramente più leggibile):

DateTime now = new DateTime();      
DateTime dt = now.dayOfMonth().withMaximumValue().withDayOfWeek(DateTimeConstants.FRIDAY);
if (dt.getMonthOfYear() != now.getMonthOfYear()) {
  dt = dt.minusDays(7);
}       
System.out.println(dt);

Devi sapere due cose: il numero di giorni del mese e il giorno della settimana in cui cade il primo del mese.

Se il primo giorno del mese è a

  • Domenica, poi l'ultimo venerdì è Sempre il 27.
  • Lunedì, poi l'ultimo venerdì è Sempre il 26.
  • Martedì, poi l'ultimo venerdì è Sempre il 25.
  • Mercoledì, quindi l'ultimo venerdì è il 24, a meno che non ci siano 31 giorni nel mese, allora è il 31
  • Giovedì, quindi l'ultimo venerdì è il 23, a meno che non ci siano 30 giorni o più nel mese, allora è il 30.
  • Venerdì, quindi l'ultimo venerdì è il 22, a meno che non ci siano 29 giorni o più nel mese, allora è il 29.
  • Sabato, poi l'ultimo venerdì è Sempre il 28.

Ci sono solo tre casi speciali.Una singola istruzione switch e tre istruzioni if ​​(o operatori ternari se preferisci che ogni caso abbia una sola riga...)

Elaboralo su carta.Non sono necessarie librerie speciali, funzioni, conversioni giuliane, ecc. (beh, tranne per ottenere il giorno della settimana in cui cade il primo e forse il numero di giorni di quel mese...)

Aaron lo ha implementato in Java.

-Adamo

codice per Algoritmo di Adam Davis

public static int getLastFriday(int month, int year)
{
Calendar cal = Calendar.getInstance();
cal.set(year, month, 1, 0, 0, 0); // set to first day of the month
cal.set(Calendar.MILLISECOND, 0);

int firstDay = cal.get(Calendar.DAY_OF_WEEK);
int daysOfMonth = cal.getMaximum(Calendar.DAY_OF_MONTH);

switch (firstDay)
{
    case Calendar.SUNDAY :
        return 27;
    case Calendar.MONDAY :
        return 26;
    case Calendar.TUESDAY :
        return 25;
    case Calendar.WEDNESDAY :
        if (daysOfMonth == 31) return 31;
        return 24;
    case Calendar.THURSDAY :
        if (daysOfMonth >= 30) return 30;
        return 23;
    case Calendar.FRIDAY :
        if (daysOfMonth >= 29) return 29;
        return 22;
    case Calendar.SATURDAY :
        return 28;
}
throw new RuntimeException("what day of the month?");
}}

Anche se sono d'accordo con scubabbl, ecco una versione senza tempo interno.

int year = 2008;
for (int m = Calendar.JANUARY; m <= Calendar.DECEMBER; m++) {
    Calendar cal = new GregorianCalendar(year, m, 1);
    cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
    int diff = Calendar.FRIDAY - cal.get(Calendar.DAY_OF_WEEK);
    if (diff > 0) {
        diff -= 7;
    }
    cal.add(Calendar.DAY_OF_MONTH, diff);
    System.out.println(cal.getTime());
}

Leggermente più facile da leggere, approccio a forza bruta:

public int getLastFriday(int month, int year) {
    Calendar cal = Calendar.getInstance();
    cal.set(year, month, 1, 0, 0, 0); // set to first day of the month
    cal.set(Calendar.MILLISECOND, 0);

    int friday = -1;
    while (cal.get(Calendar.MONTH) == month) { 
        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) { // is it a friday?
            friday = cal.get(Calendar.DAY_OF_MONTH);
            cal.add(Calendar.DAY_OF_MONTH, 7); // skip 7 days
        } else {
            cal.add(Calendar.DAY_OF_MONTH, 1); // skip 1 day
        }
    }
    return friday;
}

ecco come ottenere l'ultimo venerdì, o qualunque giorno della settimana, del mese:

Calendar thisMonth = Calendar.getInstance();
dayOfWeek = Calendar.FRIDAY; // or whatever
thisMonth.set(Calendar.WEEK_OF_MONTH, thisMonth.getActualMaximum(Calendar.WEEK_OF_MONTH);;
thisMonth.set(Calendar.DAY_OF_WEEK, dayOfWeek);
int lastDay = thisMonth.get(Calendar.DAY_OF_MONTH); // this should be it.

Il programma seguente è per l'ultimo venerdì di ogni mese.può essere utilizzato per ottenere l'ultimo di qualsiasi giorno della settimana in qualsiasi mese.La variabile offset=0 significa mese corrente(data di sistema), offset=1 significa mese prossimo e così via.IL getLastFridayofMonth(int offset) il metodo restituirà l'ultimo venerdì.

import java.text.SimpleDateFormat;
import java.util.Calendar;

public class LastFriday {

  public static Calendar getLastFriday(Calendar cal,int offset){
    int dayofweek;//1-Sunday,2-Monday so on....
    cal.set(Calendar.MONTH,cal.get(Calendar.MONTH)+offset);
    cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); //set calendar to last day of month
    dayofweek=cal.get(Calendar.DAY_OF_WEEK); //get the day of the week for last day of month set above,1-sunday,2-monday etc
    if(dayofweek<Calendar.FRIDAY)  //Calendar.FRIDAY will return integer value =5 
      cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH)-7+Calendar.FRIDAY-dayofweek);
    else
      cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH)+Calendar.FRIDAY-dayofweek); 

    return cal;
  }

  public static String  getLastFridayofMonth(int offset) { //offset=0 mean current month
    final String DATE_FORMAT_NOW = "dd-MMM-yyyy";
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
    cal=getLastFriday(cal,offset);
    return sdf.format(cal.getTime()); 

  }

  public static void main(String[] args) {
    System.out.println(getLastFridayofMonth(0)); //0 = current month
    System.out.println(getLastFridayofMonth(1));//1=next month
    System.out.println(getLastFridayofMonth(2));//2=month after next month
  }

}

In Java 8, possiamo farlo semplicemente come:

LocalDate lastFridayOfMonth = LocalDate
                                    .now()
                                    .with(lastDayOfMonth())
                                    .with(previous(DayOfWeek.FRIDAY));

Sembra una soluzione perfettamente accettabile.Se funziona, usalo.Questo è un codice minimo e non c'è motivo di ottimizzarlo a meno che non sia necessario.

public static int lastSundayDate()
{
    Calendar cal = getCalendarInstance();
    cal.setTime(new Date(getUTCTimeMillis()));
    cal.set( Calendar.DAY_OF_MONTH , 25 );
    return (25 + 8 - (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY ? cal.get(Calendar.DAY_OF_WEEK) : 8));
}

Spero che questo ti aiuti..

public static void getSundaysInThisMonth(int monthNumber, int yearNumber){
    //int year =2009;
    //int dayOfWeek = Calendar.SUNDAY;
    // instantiate Calender and set to first Sunday of 2009
    Calendar cal = new GregorianCalendar();
    cal.set(Calendar.MONTH, monthNumber-1);
    cal.set(Calendar.YEAR, yearNumber);
    cal.set(Calendar.DATE, 1);
    int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
    int dateOfWeek = cal.get(Calendar.DATE);
    while (dayOfWeek  != Calendar.SUNDAY) {
       cal.set(Calendar.DATE, ++dateOfWeek);
       dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
      }
    cal.set(Calendar.DATE, dateOfWeek);

    int i = 1;
    while (cal.get(Calendar.YEAR) == yearNumber && cal.get(Calendar.MONTH)==monthNumber-1)
    {
            System.out.println("Sunday " + " " + i + ": " + cal.get(Calendar.DAY_OF_MONTH));
            cal.add(Calendar.DAY_OF_MONTH, 7);
            i++;
    }

  }
  public static void main(String args[]){
    getSundaysInThisMonth(1,2009);
  }
public static Calendar getNthDow(int month, int year, int dayOfWeek, int n) {
    Calendar cal = Calendar.getInstance();
    cal.set(year, month, 1);
    cal.set(Calendar.DAY_OF_WEEK, dayOfWeek);
    cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, n);
    return (cal.get(Calendar.MONTH) == month) && (cal.get(Calendar.YEAR) == year) ? cal : null;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top