我想以下列格式生成一系列时间(yyyy-mm-dd hh:mm:ss
),时间间隔为15分钟。我将给出开始日期和结束日期。
使用以下代码测试相同的代码。
public static void main(String[] args) throws ParseException {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-mm-dd HH:mm:ss");
DateTime dt1 = formatter.parseDateTime("2017-06-21 00:00:00");
DateTime dt2 = formatter.parseDateTime("2017-06-23 00:00:00");
DateTime dateTime1 = new DateTime(dt1);
DateTime dateTime2 = new DateTime(dt2);
List<Date> allDates = new ArrayList();
while( dateTime1.isBefore(dateTime2) ){
allDates.add( dateTime1.toDate() );
dateTime1 = dateTime1.plusMinutes(15);
System.out.println(dateTime1);
}
它生成如下输出:
2017-01-21T00:15:00.000 + 05:30
预期输出为2017-06-21 00:00:00
,它没有找到我想要的正确日期。
答案 0 :(得分:1)
使用java.time类,它取代了Joda-Time项目。将输入转换为标准格式以便于解析。
LocalDateTime.parse(
"2017-06-23 00:00:00".replace( " " , "T" )
).plus( Duration.ofMinutes( 15 ) )
如JB Nizet所述,您在格式化模式中使用的代码不正确。显然你猜测代码而不是阅读文档 - 这是一种不明智的做法。这些代码已经在Stack Overflow上被覆盖了数百次,所以显然你在这里发帖而不必费心去第一次搜索。
您正在使用Joda-Time库。该项目现在处于维护模式,团队建议迁移到java.time类。
您的输入字符串几乎符合ISO 8601标准。要完全符合要求,请使用T
替换中间的SPACE。在解析/生成字符串时,java.time类默认使用ISO 8601格式。所以不需要定义任何格式化模式。
LocalDateTime
您的输入缺少任何时区或offset-from-UTC的指示。所以我们将解析为LocalDateTime
。请注意LocalDateTime
不是真正的时刻,而不是时间轴上的实际点。如果没有时区或偏移的上下文,LocalDateTime
是不现实的。
LocalDateTime start = LocalDateTime.parse( "2017-06-21 00:00:00".replace( " " , "T" ) ) ;
LocalDateTime stop = LocalDateTime.parse( "2017-06-23 00:00:00".replace( " " , "T" ) ) ;
对于防御性编程,请确认您的开始是在停止之前。类似于stop.isAfter( start )
。
在每个循环中,添加指定的持续时间为15分钟。
Duration d = Duration.ofMinutes( 15 ) ;
LocalDateTime ldt = start ;
List< LocalDateTime > ldts = new ArrayList<>() ;
while( ! ldt.isAfter( stop ) ) { // "Not after" is a shorter way of saying "is earlier than or is equal to".
ldts.add( ldt ) ;
// Set up the next loop.
ldt = ldt.plus( d ) ;
}
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。
答案 1 :(得分:0)
首先,read the javadoc。小写mm
模式对应分钟。要获得月,您需要使用大写MM
。所以,你的格式化程序将是这样的:
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
你不需要这样做:
DateTime dateTime1 = new DateTime(dt1);
这是多余的,因为您正在创建2个相同的对象。只需使用parseDateTime
方法返回的日期即可。或者只是做:
DateTime dateTime1 = dt1;
您已经创建了DateTimeFormatter
,因此只需使用它来格式化输出。而不是:
System.out.println(dateTime1);
这样做:
System.out.println(formatter.print(dateTime1));
print
方法将以您希望的格式返回日期。
我不确定您是否要打印第一个日期(2017-06-21 00:00:00
)。如果您需要,只需更改plusMinutes
和System.out.println
行的顺序。
Joda-Time处于维护模式,正在被新API取代,所以我不建议用它来启动新项目。即使在joda's website它也说:&#34;请注意,Joda-Time被认为是一个很大程度上“完成”的项目。没有计划重大改进。如果使用Java SE 8,请迁移到java.time(JSR-310)。&#34; 。
因此,如果您可以迁移Joda-Time代码或启动新项目,请考虑使用新API。如果您使用 Java 8 ,则可以使用new java.time API。它更容易,less bugged and less error-prone than the old APIs。
如果您正在使用 Java&lt; = 7 ,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。对于 Android ,ThreeTenABP(更多关于如何使用它here)。
以下代码适用于两者。
唯一的区别是包名称(在Java 8中为java.time
而在ThreeTen Backport(或Android的ThreeTenABP中)为org.threeten.bp
),但类和方法名称是相同的。
逻辑非常相似。唯一的区别是我使用了LocalDateTime
类,并将其转换为java.util.Date
我需要知道它在什么时区。我使用了系统的默认时区,这可能是您想要的(因为您的原始代码也使用默认时区):
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime1 = LocalDateTime.parse("2017-06-21 00:00:00", formatter);
LocalDateTime dateTime2 = LocalDateTime.parse("2017-06-23 00:00:00", formatter);
List<Date> allDates = new ArrayList();
while (dateTime1.isBefore(dateTime2)) {
// get the date in the system default timezone and convert to java.util.Date
allDates.add(Date.from(dateTime1.atZone(ZoneId.systemDefault()).toInstant()));
dateTime1 = dateTime1.plusMinutes(15);
System.out.println(formatter.format(dateTime1));
}
在Java 8中,Date.from
方法可用。在ThreeTen Backport(Java 7和Android)中,您可以改为使用org.threeten.bp.DateTimeUtils
类:
allDates.add(DateTimeUtils.toDate(dateTime1.atZone(ZoneId.systemDefault()).toInstant()));