如何在java.util.Date中获取当前季度的第一个日期和最后一个日期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36493649/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the first date and last date of current quarter in java.util.Date
提问by Asanka sanjaya
I need to get the first date of the current quarteras a java.util.Date object and the last date of the current quarteras a java.util.Date object.
我需要将当前季度的第一个日期作为 java.util.Date 对象获取,并将当前季度的最后一个日期作为 java.util.Date 对象获取。
I'm using following methods to get this month first date and this month last date.
我正在使用以下方法获取本月的第一个日期和本月的最后一个日期。
private Date getThisMonthFirstDate(){
Calendar calendar = new GregorianCalendar();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.DAY_OF_MONTH, 1);
return calendar.getTime();
}
private Date getThisMonthLastDate(){
Calendar calandar = new GregorianCalendar();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.DAY_OF_MONTH,1);
calendar.add(Calendar.MONTH, 1);
calendar.add(Calendar.DATE, -1);
return calendar.getTime();
}
Is there a way to modify that function to achieve this or could anyone point out a better way?
有没有办法修改该功能来实现这一点,或者有人可以指出更好的方法吗?
Assume that Q1 = Jan Feb Mar, Q2 = Apr, May, Jun, etc.
假设 Q1 = Jan Feb Mar,Q2 = Apr、May、Jun 等。
采纳答案by Volodymyr Masliy
private static Date getFirstDayOfQuarter(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)/3 * 3);
return cal.getTime();
}
private static Date getLastDayOfQuarter(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.DAY_OF_MONTH, 1);
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();
}
This should work, but I suggest you to test it more carefully than I did. Note: Division of int values in Java returns the floor value.
这应该有效,但我建议你比我更仔细地测试它。注意:Java 中 int 值的除法返回下限值。
回答by g-t
You can use 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();
When DateTime date = new DateTime(2016, 8, 12, 1, 1, 1);
当 DateTime date = new DateTime(2016, 8, 12, 1, 1, 1);
I get:
我得到:
Fri Jul 01 00:00:00 CEST 2016
Fri Sep 30 00:00:00 CEST 2016
回答by Basil Bourque
As others mentioned, you are using outmoded classes. Sun/Oracle decided to supplant the old date-time classes with the java.time framework, a vastimprovement.
正如其他人提到的,您正在使用过时的课程。Sun/Oracle 决定用 java.time 框架取代旧的日期时间类,这是一个巨大的改进。
Avoid the old date-time classes. They really are poorly designed, confusing, and troublesome.
避免使用旧的日期时间类。它们确实设计得很差,令人困惑,而且很麻烦。
java.time
时间
The java.timeframework is built into Java 8. For Java 6 & 7, use the back-port, ThreeTen-Backport. For Android, the adaptation of that back-port, ThreeTenABP.
所述java.time框架内置的Java 8.对于Java 6和7中,使用回端口,ThreeTen-反向移植。对于 Android,该后向端口ThreeTenABP 的改编。
The java.time framework is inspired by the highly successful Joda-Time library, defined by JSR 310, and extended by the ThreeTen-Extra project. See Oracle Tutorial.
java.time 框架的灵感来自非常成功的 Joda-Time 库,该库由 JSR 310 定义,并由 ThreeTen-Extra 项目扩展。请参阅Oracle 教程。
LocalDate
LocalDate
For a date-only value, without time-of-day and without time zone, use LocalDate
built-in as part of java.time. To get the current date requires a time zone as the date varies around the world (a new day dawns earlier in the east).
对于没有时间和时区的仅日期值,使用LocalDate
内置作为 java.time 的一部分。要获得当前日期需要一个时区,因为世界各地的日期都不同(新的一天在东部更早的时候)。
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate today = LocalDate.now ( zoneId );
Quarter
& YearQuarter
Quarter
& YearQuarter
The ThreeTen-Extraproject mentioned above serves as the proving ground for possible future features to be added to java.time. To use this library, add its jar file to your project (or use Maven etc.). If you really don't want to add a library, see an alternate solution Answer by dheeran.
上面提到的ThreeTen-Extra项目作为未来可能添加到 java.time 的功能的试验场。要使用此库,请将其 jar 文件添加到您的项目中(或使用 Maven 等)。如果您真的不想添加库,请参阅dheeran的替代解决方案答案。
This library currently includes the Quarter
and YearQuarter
classes that you might find particularly useful. Safer to pass around objects of these types in your code rather than use strings and numbers to represent your quarters.
该库当前包含您可能会发现特别有用的Quarter
和YearQuarter
类。在您的代码中传递这些类型的对象比使用字符串和数字来表示您的宿舍更安全。
YearQuarter currentQuarter = YearQuarter.now ( zoneId );
The YearQuarter
has many useful methods, including asking for its dates.
在YearQuarter
具有许多有用的方法,包括要求它的日期。
LocalDate start = currentQuarter.atDay ( 1 );
LocalDate stop = currentQuarter.atEndOfQuarter ();
Dump to console.
转储到控制台。
System.out.println ( "today: " + today + " currentQuarter: " + currentQuarter + " start: " + start + " stop: " + stop );
today: 2016-04-08 currentQuarter: 2016-Q2 start: 2016-04-01 stop: 2016-06-30
今天:2016-04-08 当前季度:2016-Q2 开始:2016-04-01 停止:2016-06-30
If you really do not want to add the ThreeTen-Extralibrary as I recommended, see the Answer by Pavelfor another solution using only the built-in java.timeclasses. But if you are doing much work with quarters, I am sure you'll find ThreeTen-Extrato be well worth the trouble of adding a library to your project.
如果您真的不想按照我的建议添加ThreeTen-Extra库,请参阅Pavel的答案以获取仅使用内置java.time类的另一种解决方案。但是,如果您在宿舍方面做了很多工作,我相信您会发现ThreeTen-Extra非常值得为您的项目添加一个库。
Conversion
转换
If you must use java.util.Date to work with old code not yet updated to java.time, you can convert back and forth. Find new methods added to the old classes for conversion.
如果必须使用 java.util.Date 来处理尚未更新为 java.time 的旧代码,则可以来回转换。查找添加到旧类中的新方法以进行转换。
Unfortunately, the old classes lack any clean way to represent a date-only value. So there is no perfectly clean way to go to/from a LocalDate
.
不幸的是,旧类缺乏任何干净的方式来表示仅日期值。所以没有完全干净的方式去/从LocalDate
.
java.sql.Date
java.sql.Date
The java.sql.Date
class pretends to be a date-only but actually contains a time-of-day adjusted to 00:00:00.0
. This class awkwardly inherits from java.util.Date
but the doc clearly warns against using that fact; you are supposed to treat the two as separate unrelated classes.
该java.sql.Date
班假装是一个日期,但仅实际上包含调整到时间的天00:00:00.0
。此类笨拙地继承自,java.util.Date
但文档明确警告不要使用该事实;您应该将两者视为单独的不相关类。
java.sql.Date sqlDate_quarterStart = java.sql.Date.valueOf( start );
java.util.Date
java.util.Date
A java.util.Date
represents both a date and time-of-day, effectively in UTC. We can first adjust our LocalDate
into the first moment of a day to get a date with time-of-day, a ZonedDateTime
. From there we can ask for an Instant
which is a moment on the timeline in UTC. The old .Date class has a static from( Instant )
conversion method.
Ajava.util.Date
表示日期和时间,有效地使用 UTC。我们可以先将我们调整LocalDate
到一天的第一个时刻,以获得一个带有时间的日期, a 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 );
About java.time
关于java.time
The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date
, Calendar
, & SimpleDateFormat
。
The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*
classes.
您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
Where to obtain the java.time classes?
从哪里获得 java.time 类?
- Java SE 8, Java SE 9, Java SE 10, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9、Java SE 10及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- 更高版本的 Android 捆绑实现 java.time 类。
- 对于早期的 Android(<26),ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
The ThreeTen-Extraproject 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.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
回答by Pavel
Pure Java-8+ solution:
纯 Java-8+ 解决方案:
LocalDate localDate = LocalDate.now();
LocalDate firstDayOfQuarter = localDate.with(localDate.getMonth().firstMonthOfQuarter())
.with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDayOfQuarter = firstDayOfQuarter.plusMonths(2)
.with(TemporalAdjusters.lastDayOfMonth());
回答by Mohanraj Balasubramaniam
It's pretty simple with LocalDate
使用 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());
Cheers!
干杯!
回答by Pavan
you can use java 8 LocaDate to get current quarter first and last day
您可以使用 java 8 LocaDate 获取当前季度的第一天和最后一天
The code below gives you.
下面的代码给你。
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);
}
Here in second method the 92 has partially lenient
在第二种方法中,92 有部分宽松
The day-of-quarter has values from 1 to 90 in Q1 of a standard year, from 1 to 91in Q1 of a leap year, from 1 to 91 in Q2 and from 1 to 92 in Q3 and Q4
季度日的值在标准年的 Q1 中从 1 到 90,在闰年的 Q1 中从 1 到 91,在 Q2 中从 1 到 91,在 Q3 和 Q4 中从 1 到 92
see ISOFields documentation for details here
在此处查看 ISOFields 文档以获取详细信息
回答by DaithiG
Using the answer from Volodymyr Masliy using java.util.Date
, there is some bug that came up in my tests
If you enter "31/05/2000" it returns July 1st of that year, which is obviously not what we're looking for.
使用 Volodymyr Masliy using 的答案,java.util.Date
在我的测试中出现了一些错误如果您输入“31/05/2000”,它将返回当年的 7 月 1 日,这显然不是我们想要的。
I used java.time.LocalDate
as suggested by Basil Bourque and dheeran and the test case works ok.
我java.time.LocalDate
按照 Basil Bourque 和 dheeran 的建议使用,测试用例运行正常。
My method is as follows:
我的方法如下:
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());
}
My UnitTests using ZohhakRunner are as follows:
我使用 ZohhakRunner 的单元测试如下:
@TestWith({
"01/03/2000, 31/03/2000",
"05/04/1982, 30/06/1982",
"31/05/1982, 30/06/1982",
"09/07/1990, 30/09/1990",
"11/11/2019, 31/12/2019",
"31/03/2016, 31/03/2016"})
public void lastDayOfQuarter_useInputDate_returnExpectedEndOfQuarterDate(String inputDateAsString, String endOfQuarterAsString) throws ParseException{
Date inputDate = new SimpleDateFormat("dd/MM/yyyy").parse(inputDateAsString);
Date expectedDate = new SimpleDateFormat("dd/MM/yyyy").parse(endOfQuarterAsString);
Date result = DateUtils.lastDayOfQuarter(inputDate);
assertEquals(result, expectedDate);
}