Java:我怎么知道一个月的x日(比如2012年2月的第三个星期一)

时间:2022-07-30 06:09:43

I am somewhat struggling with this.

我有点挣扎。

I want to setup my Calendar to let's say: Third Monday in February 2012. And I didn't find any way of doing this using Java.

我想设置我的日历,比如:2012年2月的第三个星期一。我没有找到任何使用Java的方法。

For example, if I wanted to set my calendar for Christmas 2011, I can do this easily, this way:

例如,如果我想设置2011年圣诞节的日历,我可以很容易地做到:

Calendar when = Calendar.getInstance();
when.set (Calendar.MONTH, Calendar.DECEMBER);
when.set (Calendar.DAY_OF_MONTH, 25)
when.set (Calendar.YEAR, 2011);

But I am lost as to how to set it up for let's say Memorial Day 2012, which is the last Monday of May. This is my code, but it's obviously wrong, because I simply can't assume that the last Monday of May will be in the 4th week of May that year:

但我不知道如何为2012年的阵亡将士纪念日(Memorial Day 2012)做准备,那是5月的最后一个星期一。这是我的代码,但显然是错误的,因为我不能假设五月的最后一个星期一是在那年的五月的第四个星期:

Calendar when = Calendar.getInstance ();
when.set (Calendar.DAY_OF_WEEK,Calendar.MONDAY);
when.set (Calendar.MONTH, Calendar.MAY);
when.set (Calendar.WEEK_OF_MONTH, 4)
when.set (Calendar.YEAR, 2012);

Any suggestions as to how I can programatically find out, in which week of the month of May 2012 (in example above) is the last Monday? Assuming I can get that information, I should be able to get my code above to work.

关于我如何在程序上找到答案,有什么建议吗? 2012年5月的哪个星期是最后一个星期一?假设我能得到这些信息,我就能让我的代码运行起来。

I need something which would basically work for any other examples. Something which could give an exact day for the same scenarios. Examples:

我需要一些基本适用于其他例子的东西。同样的场景可以给出确切的日期。例子:

Which date is:

日期是:

  • 3rd Thursday of May 2015
  • 2015年5月3日星期四
  • 1st Monday of June 2050
  • 2050年6月1日。
  • 4th Tuesday of December 2012
  • 2012年12月4日星期二
  • 2nd Wednesday of July 2000
  • 2000年7月2日星期三

I really need this for my project and I am sure it's simple, but I am breaking my head on this without any real results to show for :) And also couldn't find anything on the net.

我真的很需要这个来做我的项目,我确信它很简单,但是我在这个问题上犯了错误,没有任何真正的结果可以显示:)而且在网上也找不到任何东西。


Added:

补充道:

Ok, this is where I've got for the last Monday in a month:

好的,这是我一个月后最后一个星期一要讲的内容:

when.set (GregorianCalendar.MONTH, GregorianCalendar.MAY);
when.set (GregorianCalendar.DAY_OF_WEEK, Calendar.MONDAY);
when.set (GregorianCalendar.DAY_OF_WEEK_IN_MONTH, -1);
when.set (Calendar.YEAR, 2012);

But I am not sure how would I go about doing for example seconds Monday in the same month, like this?

但是我不确定我该怎么做比如在同一个月的星期一,像这样?

when.set (GregorianCalendar.DAY_OF_WEEK_IN_MONTH, 2);

Any suggestions?

有什么建议吗?

8 个解决方案

#1


11  

To do date arithmetic in Java (and in general, to do anything with datetimes, except for the most trivial things) Joda-Time is the answer:

在Java中做日期算术(一般来说,对日期时间做任何事情,除了最琐碎的事情),Joda-Time就是答案:

public static LocalDate getNDayOfMonth(int dayweek,int nthweek,int month,int year)  {
   LocalDate d = new LocalDate(year, month, 1).withDayOfWeek(dayweek);
   if(d.getMonthOfYear() != month) d = d.plusWeeks(1);
   return d.plusWeeks(nthweek-1);
}

public static LocalDate getLastWeekdayOfMonth(int dayweek,int month,int year) {
   LocalDate d = new LocalDate(year, month, 1).plusMonths(1).withDayOfWeek(dayweek);
   if(d.getMonthOfYear() != month) d = d.minusWeeks(1);
  return d;
}

public static void main(String[] args) {
   // second wednesday of oct-2011
   LocalDate d = getNDayOfMonth( DateTimeConstants.WEDNESDAY, 2, 10, 2011);
   System.out.println(d);
   // last wednesday of oct-2011
   LocalDate dlast = getLastWeekdayOfMonth( DateTimeConstants.WEDNESDAY,  10, 2011);
   System.out.println(dlast);
}

Edit: Since Java 8 (2014) the new Date API (package java.time), which is inspired by/similar to Jodatime, should be preferred.

编辑:由于Java 8(2014)的新日期API (package Java .time)是受到/类似于Jodatime的启发,应该优先考虑。

#2


6  

The following code was successfully tested for all holidays in 2013 and 2014. I realize that this doesn't really answer the original question, but I think it might be useful for people who come across this post in hopes of figuring out how to work with holidays using Calendar.

以下代码在2013年和2014年的所有假期都成功测试。我意识到这并不能真正回答最初的问题,但我认为它可能对那些希望通过日历了解如何处理假日的人有用。

public static boolean isMajorHoliday(java.util.Date date) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);

    // check if New Year's Day
    if (cal.get(Calendar.MONTH) == Calendar.JANUARY
        && cal.get(Calendar.DAY_OF_MONTH) == 1) {
        return true;
    }

    // check if Christmas
    if (cal.get(Calendar.MONTH) == Calendar.DECEMBER
        && cal.get(Calendar.DAY_OF_MONTH) == 25) {
        return true;
    }

    // check if 4th of July
    if (cal.get(Calendar.MONTH) == Calendar.JULY
        && cal.get(Calendar.DAY_OF_MONTH) == 4) {
        return true;
    }

    // check Thanksgiving (4th Thursday of November)
    if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER
        && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 4
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) {
        return true;
    }

    // check Memorial Day (last Monday of May)
    if (cal.get(Calendar.MONTH) == Calendar.MAY
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY
        && cal.get(Calendar.DAY_OF_MONTH) > (31 - 7) ) {
        return true;
    }

    // check Labor Day (1st Monday of September)
    if (cal.get(Calendar.MONTH) == Calendar.SEPTEMBER
        && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 1
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
        return true;
    }

    // check President's Day (3rd Monday of February)
    if (cal.get(Calendar.MONTH) == Calendar.FEBRUARY
        && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
        return true;
    }

    // check Veterans Day (November 11)
    if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER
        && cal.get(Calendar.DAY_OF_MONTH) == 11) {
        return true;
    }

    // check MLK Day (3rd Monday of January)
    if (cal.get(Calendar.MONTH) == Calendar.JANUARY
        && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
        return true;
    }

    return false;

}

#3


4  

I do not know the "easy" way but I can suggest you the following.

我不知道“简单”的方法,但我可以给你以下建议。

  1. Set calendar to the first day of the month.
  2. 把日历设定在每月的第一天。
  3. Retrieve its day of the week
  4. 找回一周中的一天
  5. Calculate the date of the first Monday of the month.
  6. 计算一个月的第一个星期一的日期。
  7. Add 14 days using calendar.add() method. You will get the third Monday.
  8. 使用calendar.add()方法添加14天。你会得到第三个星期一。

#4


1  

All you need is a loop:

你所需要的只是一个循环:

public class CalculateDate {

public static void main( String ... args ) {

    Calendar c = Calendar.getInstance();
    c.set( Calendar.YEAR, 2012 );
    c.set( Calendar.MONTH , Calendar.MAY);
    c.set( Calendar.DAY_OF_MONTH, 0 );
    c.add( Calendar.DAY_OF_MONTH, -1 );

    System.out.println( c.getTime() );

    int mondaysCount = 0;

    while ( mondaysCount != 4 ) {
        c.add( Calendar.DAY_OF_MONTH, 1 );
        if ( c.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY ) {
            mondaysCount++; 
        }       
    }

    System.out.printf( "The fourth monday of may is %s", c.getTime() );     

}

}

#5


1  

tl;dr

LocalDate thirdMondayInFebruary2012 = 
    YearMonth.of( 2012 , Month.FEBRUARY )
             .atDay( 1 )
             .with( TemporalAdjusters.dayOfWeekInMonth( 3 , DayOfWeek.MONDAY ) );

…and…

…和…

LocalDate lastMondayInMay2012 = 
    YearMonth.of( 2012 , Month.MAY )
             .atDay( 1 );
             .with( TemporalAdjusters.lastInMonth( DayOfWeek.MONDAY ) );

java.time

Very easy to do using the java.time classes that now supplant both Joda-Time and the troublesome old date-time classes bundled with the earliest versions of Java.

使用java非常容易。time类现在取代了Joda-Time类和与Java早期版本绑定的麻烦的旧日期-时间类。

First we need to specify the desired month. The YearMonth class can do that. From there we get a LocalDate, a date without a time-of-day and without a time zone.

首先,我们需要指定所需的月份。一年一个月的课程可以做到这一点。从那里我们得到了一个LocalDate,一个没有时间和时区的日期。

YearMonth ym = YearMonth.of( 2012 , Month.FEBRUARY ); // Or pass '2' for 'February'.
LocalDate ld = ym.atDay( 1 );

The TemporalAdjuster interface provides for adjusting a date-time value into another date-time value. Implementations provided by the TemporalAdjusters class (notice the plural 's'). Specify a day of week using the handy DayOfWeek enum.

临时调节器接口提供了将日期时间值调整为另一个日期时间值的功能。临时调整器类提供的实现(请注意复数的's')。使用方便的每周例会指定一周中的一天。

int ordinal = 3 ; // Use '3' for 'third occurrence in month' such as '3rd Monday'.
LocalDate thirdMondayInFebruary2012 = ld.with( TemporalAdjusters.dayOfWeekInMonth( ordinal , DayOfWeek.MONDAY ) );

Tip: Rather than pass mere integers for year and month across your code base, pass objects such as YearMonth, Year, Month, and DayOfWeek. Doing so eliminates ambiguity, makes your code more self-documenting, provides types-safety, and ensures valid values.

提示:与其在代码库中传递整数,不如传递对象,如year - month、year、month和DayOfWeek。这样做可以消除歧义,使您的代码更加自我文档化,提供类型安全,并确保有效的值。


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java。time框架被构建到Java 8以及以后的版本中。这些类取代了麻烦的旧遗留日期时间类(如java.util)。日期,日历,& SimpleDateFormat。

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

现在处于维护模式的Joda-Time项目建议迁移到java。时间类。

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

要了解更多信息,请参阅Oracle教程。和搜索堆栈溢出为许多例子和解释。规范是JSR 310。

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

你可以交换java。时间对象直接与您的数据库。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要java.sql。*类。

Where to obtain the java.time classes?

在哪里获得java。时间类?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • 内置的。
    • Part of the standard Java API with a bundled implementation.
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9 adds some minor features and fixes.
    • Java 9添加了一些次要的特性和修复。
  • Java SE 8, Java SE 9,以及后来的内置。带有捆绑实现的标准Java API的一部分。Java 9添加了一些次要的特性和修复。
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
    • 大部分java。时间功能在三个回端移植到Java 6和7。
  • Java SE 6和Java SE 7大部分的Java。时间功能在三个回端移植到Java 6和7。
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • java的Android bundle实现的后续版本。时间类。
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
    • 对于早期的Android (<26), ThreeTenABP项目适用于three - backport(如上所述)。看到如何使用ThreeTenABP ....
  • Android后期版本的java捆绑包实现。时间类。对于早期的Android (<26), ThreeTenABP项目适用于three - backport(如上所述)。看到如何使用ThreeTenABP ....

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

三个额外的项目扩展了java。时间和额外的类。这个项目是java.time未来可能增加的一个试验场。你可能会在这里找到一些有用的课程,比如时间间隔、YearWeek、YearQuarter等等。

#6


0  

Any chances you are using Quartz scheduler?

你有可能使用Quartz调度器吗?

public Date date(String cronExpression) {
    return new org.quartz.CronExpression(cronExpression).
        getNextValidTimeAfter(new Date(0));
}

System.out.println(date("0 0 0 ? May Thu#3 2015"));
System.out.println(date("0 0 0 ? Jun Mon#1 2050"));
System.out.println(date("0 0 0 ? Dec Tue#4 2012"));
System.out.println(date("0 0 0 ? Jul Wed#2 2000"));

This simple code prints correct (?) results:

这个简单的代码打印出正确的(?)结果:

Thu May 21 00:00:00 CEST 2015
Mon Jun 06 00:00:00 CEST 2050
Tue Dec 25 00:00:00 CET 2012
Wed Jul 12 00:00:00 CEST 2000

The required CronExpression doesn't have any dependencies on the rest of Quartz, so you might consider copying it to your project (watch out for license!)

所需的CronExpression对Quartz的其余部分没有任何依赖,所以您可以考虑将它复制到您的项目中(小心许可证!)

Side note: the internal implementation of getNextValidTimeAfter() is 400 lines of code...

边注:getNextValidTimeAfter()的内部实现是400行代码……

#7


0  

public String nDow(int year, int month, int nweek, int nday)
{
    Calendar cdt = Calendar.getInstance();
    cdt.set(year, month -1, 1);
    return year + "-" + month + "-" + (getPosOfWeekday(cdt.get(Calendar.DAY_OF_WEEK), nday) + ((nweek - 1) *7));
}

private int getPosOfWeekday(int startday, int nday)
{
    nday = weekDayValue(nday);
    return constructCircularArray(startday).indexOf(nday) + 1;
}

private ArrayList<Integer> constructCircularArray(int weekday)
{
    ArrayList<Integer> circularArray = new ArrayList<Integer>();
    for(int i = 0; i < 7; i++)
    {
        circularArray.add(i, weekDayValue(weekday++));
    }
    return circularArray;
}

private int weekDayValue(int x)
{
    return ((x-1) % 7) + 1;
}

#8


-2  

Here is an alternative. What it does is: Get which week you want (n), and the other parameters, and return the date of the day in that week. Since Calendar gives the date of the previous month (for example 29th of February instead of 7th of March, since the 1st week of March collides with last week of Feb), the function computes the 2nd week if the date goes beyond 7 or multiples of it for each week thereof. Hope that helps.

这是一个选择。它的作用是:得到你想要的星期(n)和其他参数,然后返回星期中的一天的日期。因为日历给前一个月的日期(例如2月29日而不是3月7日,自3月1日星期碰撞与上周2月),该函数计算第二个星期如果日期超出每周7或它的倍数。希望有帮助。

public static int getNthWeekDay (int n, int day, int month, int year) {
    Calendar calendar = Calendar.getInstance();

    calendar.set(Calendar.DAY_OF_WEEK, day);
    calendar.set(Calendar.MONTH, month);
    calendar.set(Calendar.WEEK_OF_MONTH,n);
    calendar.set(Calendar.YEAR, year);
    if (calendar.get(Calendar.DATE) > n * 7) {
        calendar.set(Calendar.DAY_OF_WEEK,day);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.WEEK_OF_MONTH,day+1);

    }
    return calendar.get(Calendar.DATE);
}

#1


11  

To do date arithmetic in Java (and in general, to do anything with datetimes, except for the most trivial things) Joda-Time is the answer:

在Java中做日期算术(一般来说,对日期时间做任何事情,除了最琐碎的事情),Joda-Time就是答案:

public static LocalDate getNDayOfMonth(int dayweek,int nthweek,int month,int year)  {
   LocalDate d = new LocalDate(year, month, 1).withDayOfWeek(dayweek);
   if(d.getMonthOfYear() != month) d = d.plusWeeks(1);
   return d.plusWeeks(nthweek-1);
}

public static LocalDate getLastWeekdayOfMonth(int dayweek,int month,int year) {
   LocalDate d = new LocalDate(year, month, 1).plusMonths(1).withDayOfWeek(dayweek);
   if(d.getMonthOfYear() != month) d = d.minusWeeks(1);
  return d;
}

public static void main(String[] args) {
   // second wednesday of oct-2011
   LocalDate d = getNDayOfMonth( DateTimeConstants.WEDNESDAY, 2, 10, 2011);
   System.out.println(d);
   // last wednesday of oct-2011
   LocalDate dlast = getLastWeekdayOfMonth( DateTimeConstants.WEDNESDAY,  10, 2011);
   System.out.println(dlast);
}

Edit: Since Java 8 (2014) the new Date API (package java.time), which is inspired by/similar to Jodatime, should be preferred.

编辑:由于Java 8(2014)的新日期API (package Java .time)是受到/类似于Jodatime的启发,应该优先考虑。

#2


6  

The following code was successfully tested for all holidays in 2013 and 2014. I realize that this doesn't really answer the original question, but I think it might be useful for people who come across this post in hopes of figuring out how to work with holidays using Calendar.

以下代码在2013年和2014年的所有假期都成功测试。我意识到这并不能真正回答最初的问题,但我认为它可能对那些希望通过日历了解如何处理假日的人有用。

public static boolean isMajorHoliday(java.util.Date date) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);

    // check if New Year's Day
    if (cal.get(Calendar.MONTH) == Calendar.JANUARY
        && cal.get(Calendar.DAY_OF_MONTH) == 1) {
        return true;
    }

    // check if Christmas
    if (cal.get(Calendar.MONTH) == Calendar.DECEMBER
        && cal.get(Calendar.DAY_OF_MONTH) == 25) {
        return true;
    }

    // check if 4th of July
    if (cal.get(Calendar.MONTH) == Calendar.JULY
        && cal.get(Calendar.DAY_OF_MONTH) == 4) {
        return true;
    }

    // check Thanksgiving (4th Thursday of November)
    if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER
        && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 4
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) {
        return true;
    }

    // check Memorial Day (last Monday of May)
    if (cal.get(Calendar.MONTH) == Calendar.MAY
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY
        && cal.get(Calendar.DAY_OF_MONTH) > (31 - 7) ) {
        return true;
    }

    // check Labor Day (1st Monday of September)
    if (cal.get(Calendar.MONTH) == Calendar.SEPTEMBER
        && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 1
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
        return true;
    }

    // check President's Day (3rd Monday of February)
    if (cal.get(Calendar.MONTH) == Calendar.FEBRUARY
        && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
        return true;
    }

    // check Veterans Day (November 11)
    if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER
        && cal.get(Calendar.DAY_OF_MONTH) == 11) {
        return true;
    }

    // check MLK Day (3rd Monday of January)
    if (cal.get(Calendar.MONTH) == Calendar.JANUARY
        && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3
        && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
        return true;
    }

    return false;

}

#3


4  

I do not know the "easy" way but I can suggest you the following.

我不知道“简单”的方法,但我可以给你以下建议。

  1. Set calendar to the first day of the month.
  2. 把日历设定在每月的第一天。
  3. Retrieve its day of the week
  4. 找回一周中的一天
  5. Calculate the date of the first Monday of the month.
  6. 计算一个月的第一个星期一的日期。
  7. Add 14 days using calendar.add() method. You will get the third Monday.
  8. 使用calendar.add()方法添加14天。你会得到第三个星期一。

#4


1  

All you need is a loop:

你所需要的只是一个循环:

public class CalculateDate {

public static void main( String ... args ) {

    Calendar c = Calendar.getInstance();
    c.set( Calendar.YEAR, 2012 );
    c.set( Calendar.MONTH , Calendar.MAY);
    c.set( Calendar.DAY_OF_MONTH, 0 );
    c.add( Calendar.DAY_OF_MONTH, -1 );

    System.out.println( c.getTime() );

    int mondaysCount = 0;

    while ( mondaysCount != 4 ) {
        c.add( Calendar.DAY_OF_MONTH, 1 );
        if ( c.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY ) {
            mondaysCount++; 
        }       
    }

    System.out.printf( "The fourth monday of may is %s", c.getTime() );     

}

}

#5


1  

tl;dr

LocalDate thirdMondayInFebruary2012 = 
    YearMonth.of( 2012 , Month.FEBRUARY )
             .atDay( 1 )
             .with( TemporalAdjusters.dayOfWeekInMonth( 3 , DayOfWeek.MONDAY ) );

…and…

…和…

LocalDate lastMondayInMay2012 = 
    YearMonth.of( 2012 , Month.MAY )
             .atDay( 1 );
             .with( TemporalAdjusters.lastInMonth( DayOfWeek.MONDAY ) );

java.time

Very easy to do using the java.time classes that now supplant both Joda-Time and the troublesome old date-time classes bundled with the earliest versions of Java.

使用java非常容易。time类现在取代了Joda-Time类和与Java早期版本绑定的麻烦的旧日期-时间类。

First we need to specify the desired month. The YearMonth class can do that. From there we get a LocalDate, a date without a time-of-day and without a time zone.

首先,我们需要指定所需的月份。一年一个月的课程可以做到这一点。从那里我们得到了一个LocalDate,一个没有时间和时区的日期。

YearMonth ym = YearMonth.of( 2012 , Month.FEBRUARY ); // Or pass '2' for 'February'.
LocalDate ld = ym.atDay( 1 );

The TemporalAdjuster interface provides for adjusting a date-time value into another date-time value. Implementations provided by the TemporalAdjusters class (notice the plural 's'). Specify a day of week using the handy DayOfWeek enum.

临时调节器接口提供了将日期时间值调整为另一个日期时间值的功能。临时调整器类提供的实现(请注意复数的's')。使用方便的每周例会指定一周中的一天。

int ordinal = 3 ; // Use '3' for 'third occurrence in month' such as '3rd Monday'.
LocalDate thirdMondayInFebruary2012 = ld.with( TemporalAdjusters.dayOfWeekInMonth( ordinal , DayOfWeek.MONDAY ) );

Tip: Rather than pass mere integers for year and month across your code base, pass objects such as YearMonth, Year, Month, and DayOfWeek. Doing so eliminates ambiguity, makes your code more self-documenting, provides types-safety, and ensures valid values.

提示:与其在代码库中传递整数,不如传递对象,如year - month、year、month和DayOfWeek。这样做可以消除歧义,使您的代码更加自我文档化,提供类型安全,并确保有效的值。


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java。time框架被构建到Java 8以及以后的版本中。这些类取代了麻烦的旧遗留日期时间类(如java.util)。日期,日历,& SimpleDateFormat。

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

现在处于维护模式的Joda-Time项目建议迁移到java。时间类。

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

要了解更多信息,请参阅Oracle教程。和搜索堆栈溢出为许多例子和解释。规范是JSR 310。

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

你可以交换java。时间对象直接与您的数据库。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要java.sql。*类。

Where to obtain the java.time classes?

在哪里获得java。时间类?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • 内置的。
    • Part of the standard Java API with a bundled implementation.
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9 adds some minor features and fixes.
    • Java 9添加了一些次要的特性和修复。
  • Java SE 8, Java SE 9,以及后来的内置。带有捆绑实现的标准Java API的一部分。Java 9添加了一些次要的特性和修复。
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
    • 大部分java。时间功能在三个回端移植到Java 6和7。
  • Java SE 6和Java SE 7大部分的Java。时间功能在三个回端移植到Java 6和7。
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • java的Android bundle实现的后续版本。时间类。
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
    • 对于早期的Android (<26), ThreeTenABP项目适用于three - backport(如上所述)。看到如何使用ThreeTenABP ....
  • Android后期版本的java捆绑包实现。时间类。对于早期的Android (<26), ThreeTenABP项目适用于three - backport(如上所述)。看到如何使用ThreeTenABP ....

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

三个额外的项目扩展了java。时间和额外的类。这个项目是java.time未来可能增加的一个试验场。你可能会在这里找到一些有用的课程,比如时间间隔、YearWeek、YearQuarter等等。

#6


0  

Any chances you are using Quartz scheduler?

你有可能使用Quartz调度器吗?

public Date date(String cronExpression) {
    return new org.quartz.CronExpression(cronExpression).
        getNextValidTimeAfter(new Date(0));
}

System.out.println(date("0 0 0 ? May Thu#3 2015"));
System.out.println(date("0 0 0 ? Jun Mon#1 2050"));
System.out.println(date("0 0 0 ? Dec Tue#4 2012"));
System.out.println(date("0 0 0 ? Jul Wed#2 2000"));

This simple code prints correct (?) results:

这个简单的代码打印出正确的(?)结果:

Thu May 21 00:00:00 CEST 2015
Mon Jun 06 00:00:00 CEST 2050
Tue Dec 25 00:00:00 CET 2012
Wed Jul 12 00:00:00 CEST 2000

The required CronExpression doesn't have any dependencies on the rest of Quartz, so you might consider copying it to your project (watch out for license!)

所需的CronExpression对Quartz的其余部分没有任何依赖,所以您可以考虑将它复制到您的项目中(小心许可证!)

Side note: the internal implementation of getNextValidTimeAfter() is 400 lines of code...

边注:getNextValidTimeAfter()的内部实现是400行代码……

#7


0  

public String nDow(int year, int month, int nweek, int nday)
{
    Calendar cdt = Calendar.getInstance();
    cdt.set(year, month -1, 1);
    return year + "-" + month + "-" + (getPosOfWeekday(cdt.get(Calendar.DAY_OF_WEEK), nday) + ((nweek - 1) *7));
}

private int getPosOfWeekday(int startday, int nday)
{
    nday = weekDayValue(nday);
    return constructCircularArray(startday).indexOf(nday) + 1;
}

private ArrayList<Integer> constructCircularArray(int weekday)
{
    ArrayList<Integer> circularArray = new ArrayList<Integer>();
    for(int i = 0; i < 7; i++)
    {
        circularArray.add(i, weekDayValue(weekday++));
    }
    return circularArray;
}

private int weekDayValue(int x)
{
    return ((x-1) % 7) + 1;
}

#8


-2  

Here is an alternative. What it does is: Get which week you want (n), and the other parameters, and return the date of the day in that week. Since Calendar gives the date of the previous month (for example 29th of February instead of 7th of March, since the 1st week of March collides with last week of Feb), the function computes the 2nd week if the date goes beyond 7 or multiples of it for each week thereof. Hope that helps.

这是一个选择。它的作用是:得到你想要的星期(n)和其他参数,然后返回星期中的一天的日期。因为日历给前一个月的日期(例如2月29日而不是3月7日,自3月1日星期碰撞与上周2月),该函数计算第二个星期如果日期超出每周7或它的倍数。希望有帮助。

public static int getNthWeekDay (int n, int day, int month, int year) {
    Calendar calendar = Calendar.getInstance();

    calendar.set(Calendar.DAY_OF_WEEK, day);
    calendar.set(Calendar.MONTH, month);
    calendar.set(Calendar.WEEK_OF_MONTH,n);
    calendar.set(Calendar.YEAR, year);
    if (calendar.get(Calendar.DATE) > n * 7) {
        calendar.set(Calendar.DAY_OF_WEEK,day);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.WEEK_OF_MONTH,day+1);

    }
    return calendar.get(Calendar.DATE);
}