如何在java.util.Date中获取当前季度的第一个日期和最后日期

时间:2016-04-08 07:12:12

标签: java date

我需要将当前季度的第一个日期作为java.util.Date对象,将当前季度的最后日期作为java.util。日期对象。

我正在使用以下方法来获取本月的第一个日期和本月的最后一个日期。

diff

有没有办法修改这个功能来实现这个目标,还是有人能指出更好的方法?

假设Q1 = 1月2月3月,Q2 = 4月,5月,6月等

8 个答案:

答案 0 :(得分:13)

Pure Java-8 +解决方案:

LocalDate localDate = LocalDate.now();
LocalDate firstDayOfQuarter = localDate.with(localDate.getMonth().firstMonthOfQuarter())
    .with(TemporalAdjusters.firstDayOfMonth());

LocalDate lastDayOfQuarter = firstDayOfQuarter.plusMonths(2)
    .with(TemporalAdjusters.lastDayOfMonth());

答案 1 :(得分:12)

private static Date getFirstDayOfQuarter(Date date) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)/3 * 3);
    cal.set(Calendar.DAY_OF_MONTH, 1);
    return cal.getTime();
}

private static Date getLastDayOfQuarter(Date date) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)/3 * 3 + 2);
    cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
    return cal.getTime();
}

这应该可行,但我建议你比我更仔细地测试它。 注意:Java中的int值分区返回最低值。

答案 2 :(得分:3)

正如其他人提到的,你正在使用过时的类。 Sun / Oracle决定用java.time框架取代旧的日期时间类,浩大的改进。

避免使用旧的日期时间类。他们的设计很糟糕,令人困惑,也很麻烦。

java.time

{8}框架内置于Java 8中。对于Java 6& 7,使用后端口java.time。对于Android,改编后端口ThreeTen-Backport

java.time框架的灵感来自非常成功的Joda-Time库,由JSR 310定义,并由ThreeTen-Extra项目扩展。请参阅ThreeTenABP

LocalDate

对于仅限日期的值,没有时间和没有时区,请使用内置Oracle Tutorial作为java.time的一部分。要获得当前日期需要一个时区,因为日期在世界各地不同(东部早些时候开始新的一天)。

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate today = LocalDate.now ( zoneId );

Quarter& YearQuarter

上面提到的LocalDate项目可以作为未来可能添加到java.time的功能的试验场。要使用此库,请将其jar文件添加到项目中(或使用Maven等)。如果您确实不想添加库,请参阅备用解决方案ThreeTen-Extra

此库目前包含您可能认为特别有用的Answer by dheeranQuarter类。更安全的是在代码中传递这些类型的对象,而不是使用字符串和数字来表示您的宿舍。

YearQuarter currentQuarter = YearQuarter.now ( zoneId );

YearQuarter有许多有用的方法,包括询问其日期。

LocalDate start = currentQuarter.atDay ( 1 );
LocalDate stop = currentQuarter.atEndOfQuarter ();

转储到控制台。

System.out.println ( "today: " + today + " currentQuarter: " + currentQuarter + " start: " + start + " stop: " + stop );
  今天:2016-04-08当前季度:2016年第2季度开始:2016-04-01停止:2016-06-30

如果您确实不想按我的建议添加 ThreeTen-Extra 库,请参阅YearQuarter以获取仅使用内置 java.time <的其他解决方案/ em>类。但是如果你在宿舍里做了很多工作,我相信你会发现 ThreeTen-Extra 非常值得为你的项目添加一个库。

转换

如果必须使用java.util.Date来处理尚未更新到java.time的旧代码,则可以来回转换。找到添加到旧类进行转换的新方法。

不幸的是,旧类没有任何干净的方式来表示仅限日期的值。所以没有一个完全干净的方式去往/来自LocalDate

java.sql.Date

Answer by Pavel类假装只是一个日期,但实际上包含一个调整为00:00:00.0的时间。这个类笨拙地继承自java.util.Date但是文档明确警告不要使用这个事实;你应该把这两个视为单独的不相关的类。

java.sql.Date sqlDate_quarterStart = java.sql.Date.valueOf( start );

java.util.Date

java.sql.Date代表日期和时间,实际上是UTC。我们可以先将LocalDate调整为一天中的第一个时刻,以获得一个时间日期ZonedDateTime。从那里我们可以要求Instant这是UTC时间轴上的一个时刻。旧的.Date类具有静态from( Instant )转换方法。

ZonedDateTime zdt = start.atStartOfDay( zoneId ); // First moment of the day on a certain date.
Instant instant = zdt.toInstant(); // Moment on the timeline in UTC.
java.util.Date utilDate = java.util.Date.from( instant );

关于 java.time

java.util.Date框架内置于Java 8及更高版本中。这些类取代了麻烦的旧java.time日期时间类,例如legacyjava.util.Date和&amp; Calendar

现在位于SimpleDateFormatJoda-Time项目建议迁移到maintenance mode类。

要了解详情,请参阅java.time。并搜索Stack Overflow以获取许多示例和解释。规范是Oracle Tutorial

您可以直接与数据库交换 java.time 对象。使用符合JSR 310或更高版本的JDBC driver。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

How to use ThreeTenABP…项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如ThreeTen-ExtraIntervalYearWeekYearQuarter

答案 3 :(得分:2)

使用LocalDate非常简单

LocalDate inputDate = LocalDate.parse("2018-09-04");
LocalDate firstDayOfQuarter = inputDate.withMonth(inputDate.get(IsoFields.QUARTER_OF_YEAR) * 3 - 2).with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDayOfQuarter = inputDate.withMonth(inputDate.get(IsoFields.QUARTER_OF_YEAR) * 3).with(TemporalAdjusters.lastDayOfMonth());

干杯!

答案 4 :(得分:1)

保持简单

我认为以下内容是最优雅的,因为它没有任何神奇的数字(例如92),TemporalAdjusters或非显而易见的计算,并且可以轻松地进行调整以获取任何季度的开始和结束(而不仅仅是当前季度) )。

import static java.time.temporal.IsoFields.QUARTER_OF_YEAR;

LocalDate date = LocalDate.now(); // can be any other date

int year = date.getYear();
int quarter = date.get(QUARTER_OF_YEAR);
        
LocalDate start = YearMonth.of(year, 1)                    // January of given year
                           .with(QUARTER_OF_YEAR, quarter) // becomes first month of given quarter
                           .atDay(1);                      // becomes first day of given quarter

LocalDate end = YearMonth.of(year, 3)                      // March of given year
                         .with(QUARTER_OF_YEAR, quarter)   // becomes 3rd (last) month of given quarter
                         .atEndOfMonth();                  // becomes last day of given quarter

如果您没有日期,而只有一年和一个季度(例如2020年第二季度),则将变为:

LocalDate start = YearMonth.of(2020, 1).with(QUARTER_OF_YEAR, 2).atDay(1);
LocalDate end = YearMonth.of(2020, 3).with(QUARTER_OF_YEAR, 2).atEndOfMonth();

答案 5 :(得分:0)

你可以使用joda:

Date start = date.withMonthOfYear(((date.getMonthOfYear() / 3) + 1) * 3 - 2)
            .withDayOfMonth(1)
            .withTimeAtStartOfDay()
            .toDate();
Date end = date.withMonthOfYear(((date.getMonthOfYear() / 3) + 1) * 3)
            .withDayOfMonth(Month.of(((date.getMonthOfYear() / 3) + 1) * 3).maxLength())
            .withTimeAtStartOfDay()
            .toDate();

当DateTime date = new DateTime(2016,8,12,1,1,1);

我明白了:

Fri Jul 01 00:00:00 CEST 2016
Fri Sep 30 00:00:00 CEST 2016

答案 6 :(得分:0)

您可以使用Java 8 LocaDate获取当前季度的第一天和最后一天

下面的代码为您提供。

public static LocalDate getCurrentQuarterStartDay(LocalDate date) {
        return date.with(IsoFields.DAY_OF_QUARTER, 1L);
    }

public static LocalDate getCurrentQuarterEndDate(LocalDate date) {
        return date.with(IsoFields.DAY_OF_QUARTER, 92L);
    }

在第二种方法中,92具有部分宽容度

标准日第一季度的季度值从1到90,a年第一季度的季度值从1到91,第二季度从1到91,第三和第四季度从1到92

有关详细信息,请参见ISOFields文档here

答案 7 :(得分:0)

使用来自C:/Users/amlut/Downloads/C/run/main.c:11: undefined reference to `_imp__Tcl_CreateInterp' C:/Users/amlut/Downloads/C/run/main.c:12: undefined reference to `_imp__Tcl_Eval' 的Volodymyr Masliy的答案,我的测试中出现了一些错误 如果输入“ 31/05/2000”,它将返回该年7月1日,这显然不是我们想要的。

我根据Basil Bourque和dheeran的建议使用了java.util.Date,测试用例可以正常工作。

我的方法如下:

java.time.LocalDate

我使用ZohhakRunner进行的单元测试如下:

public static Date lastDayOfQuarter(Date date) {
    LocalDate inputDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    LocalDate lastDayOfQuarter = inputDate.withMonth(inputDate.get(IsoFields.QUARTER_OF_YEAR) * 3).with(TemporalAdjusters.lastDayOfMonth());
    return Date.from(LastDayOfQuarter.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}