2008-09-16 6 views
14

Je travaille sur un projet où l'exigence est d'avoir une date calculée comme étant le dernier vendredi d'un mois donné. Je pense avoir une solution qui n'utilise que du Java standard, mais je me demandais si quelqu'un connaissait quelque chose de plus concis ou efficace. Voici ce que je l'ai testé avec pour cette année:Recevez le dernier vendredi du mois en Java

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()); 
    } 

Répondre

23

Basé sur marked23's suggestion:

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(); 
} 
+0

Grande réponse, mais pourquoi utiliser le calendrier Gregorian concret plutôt que le calendrier abstrait retourné par Calendar.getInstance()? –

+1

bonne réponse. semble être le plus court et le plus concis. Je modifierais à nouveau si je pouvais. – Randyaa

+0

cal.get (Calendar.DAY_OF_WEEK)% 7 + 1; Le% 7 + 1 est complètement inutile ici. cal.get (Calendar.DAY_OF_WEEK) retournera une valeur de 1 à 7 ici (dimanche étant 1, samedi étant 7).Modding par 7 puis en ajoutant 1 ne fait rien littéralement. –

0

Il y a un certain nombre de méthodes utiles pour calculating the day of the week. Avec un peu d'algèbre ajoutée, l'un d'eux devrait être adaptable à votre problème.

1

Cela ressemble à une solution parfaitement acceptable. Si cela fonctionne, utilisez-le. C'est un code minimal et il n'y a aucune raison de l'optimiser à moins d'y être obligé.

+0

Désolé, ce code n'est ni minimal, bon, ni même correct ... –

1

Cela ne fonctionnera pas. Votre boucle va boucler 13 fois (de 0 à 12).

+0

À quelle réponse est-ce que cela se réfère? –

+0

Il se réfère à la question –

1

un peu plus facile à lire, approche force brute:

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; 
} 
6

J'utiliser une bibliothèque comme Jodatime. Il a une API très utile et utilise des numéros de mois normaux. Et le meilleur de tous, c'est thread safe.

Je pense que vous pouvez avoir une solution (mais peut-être pas le plus court, mais certainement plus lisible):

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); 
8

Vous ne devez jamais boucle pour trouver cela. Pour déterminer la date du «dernier vendredi» pour ce mois, commencez par le premier jour du mois suivant. Soustrayez le nombre de jours approprié en fonction du jour (numérique) de la semaine où tombe le premier jour du mois. Il y a ton "dernier vendredi". Je suis à peu près sûr qu'il peut être réduit à un long-paquebot, mais je ne suis pas un dev java. Je vais donc laisser ça à quelqu'un d'autre.

1

Bien que je suis d'accord avec scubabbl, voici une version sans un moment intérieur.

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()); 
} 
2

Vous devez connaître deux choses: le nombre de jours dans le mois et le jour de la semaine du premier jour du mois.

Si le premier jour du mois est un dimanche

  • , le vendredi dernier est toujours le 27.
  • Lundi, puis le dernier vendredi est toujours le 26.
  • Mardi, puis le dernier vendredi est toujours le 25.
  • Mercredi, alors le dernier vendredi est le 24, sauf s'il y a 31 jours dans le mois, alors c'est le 31e
  • Jeudi, alors le dernier vendredi est le 23, sauf s'il y a 30 jours ou plus dans le mois, alors c'est le 30ème.
  • Vendredi, alors le dernier vendredi est le 22, à moins qu'il y ait 29 jours ou plus dans le mois, alors c'est le 29. Samedi, puis le dernier vendredi est toujours le 28e.

Il existe seulement trois cas particuliers.Une seule instruction switch et trois instructions if (ou des opérateurs ternaires si vous préférez que chaque cas ait une seule ligne ...)

Travailler sur papier. Ne pas besoin de bibliothèques spéciales, les fonctions, les conversions julian, etc (bien, sauf pour obtenir le jour de la semaine le 1er tombe, et peut-être le nombre de jours du mois ...)

Aaron implemented it in Java.

-Adam

0

solution de ColinD ne devrait pas fonctionner: essayez d'exécuter avec Décembre 2008 et il va essayer de régler le 13e mois d'une année. Cependant, remplacer "cal.set (...)" par "cal.add (Calendar.MONTH, 1)" devrait fonctionner correctement.

+1

En fait, cela fonctionne bien avec Décembre 2008 et parce qu'un Calendrier est indulgent par défaut. Et vous ne pouvez pas simplement remplacer cal.set() par cal.add() parce que vous ne serez pas au premier jour du mois. –

2

code pour Adam Davis's algorithm

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?"); 
}} 
+0

Génial! Merci. –

0

Hope this helps ..

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); 
    } 
31

Let Calendar.class sa magie pour vous;)

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

Ceci est la meilleure réponse. Je cherchais juste cela et tout ce que j'avais à faire était de lire la documentation pour DAY_OF_WEEK_IN_MONTH ... ou cette réponse. – Allen

+0

Fonctionne comme un charme, merci. –

+0

Le plus simple et le meilleur – Axel

1

est ici comment obtenir le dernier vendredi, ou peu importe le jour de la semaine, du mois:

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. 
0
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; 
} 
1

Le programme ci-dessous correspond au dernier vendredi de chaque mois. il peut être utilisé pour obtenir le dernier de n'importe quel jour de la semaine dans un mois. La variable offset=0 signifie mois courant (date du système), offset = 1 signifie le mois prochain, etc. La méthode getLastFridayofMonth(int offset) renverra le dernier vendredi.

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 
    } 

} 
0
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)); 
} 
4

java.time

Utilisation de la bibliothèque java.time intégrée dans Java 8 et versions ultérieures:

import java.time.{DayOfWeek, LocalDate} 
import java.time.temporal.TemporalAdjusters.lastInMonth 

val now = LocalDate.now() # 2015-11-23 
val lastInMonth = now.`with`(lastInMonth(DayOfWeek.FRIDAY)) # 2015-11-27 

Vous pouvez choisir un jour de la DayOfWeek ENUM: java.time.DayOfWeek.{MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}.

Si vous avez besoin d'ajouter des informations de temps, vous pouvez utiliser tout disponible LocalDate-LocalDateTime conversion comme

lastFriday.atStartOfDay() # 2015-11-27T00:00 
+0

Un meilleur remplacement de 'GregorianCalendar' serait [' ZonedDateTime'] (http://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html) plutôt que 'LocalDateTime'. Le "Local" signifie * toute * localité, sans aucun fuseau horaire particulier, donc il ne représente * pas * un moment spécifique sur la ligne temporelle. En revanche, un 'ZonedDateTime' est un moment spécifique sur la timeline, avec un fuseau horaire assigné ([' ZoneId']) (http://docs.oracle.com/javase/8/docs/api/java/time/ZoneId .html)). –

+0

En appelant 'LocalDate.now', je suggère toujours de passer le fuseau horaire désiré/attendu, [' ZoneId'] (http://docs.oracle.com/javase/8/docs/api/java/time/ZoneId. html). S'il est omis, le fuseau horaire par défaut actuel de la JVM est appliqué silencieusement. Cette valeur par défaut peut être modifiée à tout moment * pendant l'exécution * par n'importe quel code dans n'importe quelle application de n'importe quel thread de la JVM. Il est donc imprudent de dépendre d'une telle valeur. –

1

En Java 8, nous pouvons le faire simplement:

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