我尝试根据当前加上30,60,90天之前和之后的3天计算日期窗口。除了这种肮脏的方式,我真的不能用日历做正确的方法。
public static void main(String []args) throws ParseException {
Calendar cal = GregorianCalendar.getInstance();
System.out.println("Curent date is " + cal.getTime() + "\n");
int [] remainingPeriodArr = {30,60,90,180};
int [] expiredArr = {30,60,90};
for(int i = 0; i < remainingPeriodArr.length; i++) {
getSupportPeriod(remainingPeriodArr[i]);
}
for(int i = 0; i < expiredArr.length; i++) {
getSupportPeriod(expiredArr[i]);
}
}
public static void getSupportPeriod(int period) {
Calendar c1 = GregorianCalendar.getInstance();
c1.add(Calendar.DATE, -3);
c1.add(Calendar.DATE, period);
System.out.println( period + " days from prior window " + c1.getTime() + "\n");
Calendar c2 = GregorianCalendar.getInstance();
c2.add(Calendar.DATE, 3);
// Date d2 = c2.getTime();
c2.add(Calendar.DATE, period);
System.out.println( period+ " days in the future window " + c2.getTime() + "\n");
}
}
答案 0 :(得分:0)
除了新的JDK8日期库或Joda Time,最简单的方法是以毫秒为单位处理当前时间:
long now = System.currentTimeMilliseconds();
long threeDaysAgoMillis = now - (3 * 24 * 60 * 60 * 1000);
long nowPlus30Millis = now + (30 * 24 * 60 * 60 * 1000);
Date threeDaysAgo = new Date(threeDaysAgoMillis);
Date nowPlus30 = new Date(nowPlus30Millis);
如果您使用的是JDK8,请查看this tutorial。如果您可以使用Joda时间,请查看here。
答案 1 :(得分:0)
如果你采用旧的JDK方式,那么请注意以下陷阱:
A)一般避免使用继承的静态方法,但使用具体的值对象类型。
Calendar c1 = GregorianCalendar.getInstance();
更好用:
GregorianCalendar c1 = new GregorianCalendar();
为什么呢?如果你在泰国,你将不会通过在GregorianCalendar-class上使用静态Calendar方法获得您的方法的格里历。相反,你得到佛教日历。
B)根据您的问题使用特定于域的类型
不幸的是,GregorianCalendar不是一个仅限日期的类型,因此它不能很好地满足您对日期算术的要求。在旧的JDK中根本没有这种类型,所以你必须忍受丑陋的工作。在Java 8中,您可以使用java.time.LocalDate
,在JodaTime中您可以使用org.joda.time.LocalDate
。在我即将到来的时间库中,您可以使用net.time4j.PlainDate
(本月仍会首次发布)。
C)否则尝试模仿普通日期类型
使用GregorianCalendar
您需要将所有时间字段清零,即:
gcal.set(year, month, dayOfMonth);
gcal.set(Calendar.HOUR_OF_DAY, 0);
gcal.set(Calendar.MINUTE, 0);
gcal.set(Calendar.SECOND, 0);
gcal.set(Calendar.MILLISECOND, 0);
请注意,这种方法在与时区偏移变化相关的一些罕见情况下并不完美,但在美国和欧洲可能已足够。
如果您评估此类日历对象作为add(Calendar.DATE, period)
等附加操作的结果,则只应打印其日期部分并忽略时间部分 - 在大多数情况下,通过根据您的本地或作为日期选择仅限日期的格式ISO-8601格式(主要限于年,月,日)。
如果比较这些日历对象,则不要根据方法getTime()应用比较,但只能通过显式提取年,月和日(写一个专门的Comparator
是一个好主意)。
D)避免自制日期/时间算术,信任库
如果您在此期间有夏令时切换,则long nowPlus30Millis = now + (30 * 24 * 60 * 60 * 1000);
之类的代码可能会失败。 java.util.GregorianCalendar的add() - 方法可以考虑到这一点,但通常不是自制的算法。
答案 2 :(得分:0)
LocalDate.now().plusDays( 3 )
现代方法使用 java.time 类。
LocalDate
LocalDate
类表示没有时间且没有时区的仅限日期的值。
时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,在Paris France午夜后的几分钟是新的一天,而Montréal Québec中仍然是“昨天”。
如果未指定时区,则JVM会隐式应用其当前的默认时区。该默认值可能随时更改,因此您的结果可能会有所不同。最好明确指定您期望/预期的时区作为参数。
以continent/region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
如果要使用JVM的当前默认时区,请求它并作为参数传递。如果省略,则隐式应用JVM的当前默认值。最好是明确的,因为默认情况下可以在运行时期间由JVM中任何应用程序的任何线程中的任何代码随时更改。
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
或指定日期。您可以将月份设置为一个数字,1月至12月的数字为1-12。
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
或者,更好的是,使用预定义的Month
枚举对象,一年中的每个月一个。提示:在整个代码库中使用这些Month
对象,而不仅仅是整数,以使代码更具自我记录功能,确保有效值,并提供type-safety。
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
添加天数的一种方法是使用LocalDate::plusDays
方法。类似于减法。
LocalDate later = ld.plusDays( 3 ) ;
LocalDate earlier = ld.minusDays( 3 ) ;
或者,使用对象来表示要添加或减去的时间跨度。这样做的好处是能够使用变量名称标记您的时间跨度。对于数月 - 天,请使用Period
。对于小时 - 分钟 - 秒,请使用Duration
。
Period periodBookIsLate = Period.ofDays( 3 ) ;
LocalDate dueDate = ld.plus( periodBookIsLate ) ;
LocalDateRange
您可以在 ThreeTen-Extra 项目中找到有用的LocalDateRange
类。
LocalDateRange thirtyDayRange = LocalDateRange.of( ld.minusDays( 30 ) , ld.plusDays( 30 ) ) ;
了解该类中的方便方法,例如abuts,contains,intersection等。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。