我正在尝试在Java中创建一个函数,该函数在给定开始日期和结束日期的情况下生成季度日期序列。
例如,在R中,我可以这样做:
generateQuarterlySequence = function(startDate, endDate)
{
require(zoo)
# Generate date sequence
dateSequence = seq.Date(from = as.Date(startDate),
to = as.Date(endDate),
by = "quarter")
# Convert to quarters
dateSequence = as.yearqtr(dateSequence, format = "%Y-%m-%d")
# Get rid of extra white space
dateSequence = gsub(" ", "", dateSequence)
return(dateSequence)
}
generateQuarterlySequence(startDate = "2017-06-30", endDate = "2017-12-31")
[1] "2017Q2" "2017Q3" "2017Q4"
任何摇滚明星都在关注如何在Java中完成这项工作?你会让这个Java初学者非常开心!
干杯, 乔
答案 0 :(得分:4)
我知道在评论中我建议ThreeTen-Extra。但是,这是一个使用纯mel.eval("catchQuiet(`python(\"cmds.file('/drive/myfile.obj', i=1)\")`)")
作为内置于Java 8及更高版本的解决方案,可通过ThreeTen Backport在Java 6和7中使用。
java.time
使用您的示例参数尝试:
public static List<String> generateQuarterlySequence(LocalDate startDate, LocalDate endDate) {
// first truncate startDate to first day of quarter
int startMonth = startDate.getMonthValue();
startMonth-= (startMonth - 1) % 3;
startDate = startDate.withMonth(startMonth).withDayOfMonth(1);
DateTimeFormatter quarterFormatter
= DateTimeFormatter.ofPattern("uuuuQQQ", Locale.ENGLISH);
List<String> quarterSequence = new ArrayList<>();
// iterate thorough quarters
LocalDate currentQuarterStart = startDate;
while (! currentQuarterStart.isAfter(endDate)) {
quarterSequence.add(currentQuarterStart.format(quarterFormatter));
currentQuarterStart = currentQuarterStart.plusMonths(3);
}
return quarterSequence;
}
打印
System.out.println(generateQuarterlySequence(LocalDate.of(2017, Month.JUNE, 30),
LocalDate.of(2017, Month.DECEMBER, 31)));
答案 1 :(得分:2)
YearQuarter.from( LocalDate.parse( "2017-06-30" ) )
.plusQuarters( 1 )
org.threeten.extra.YearQuarter
使用java.time的其他Answer by Ole V.V.很好。或者,这里是使用YearQuarter
项目中的ThreeTen-Extra类的代码,该类扩展了具有附加功能的java.time。如果您在宿舍中做了很多工作,您会发现将ThreeTen-Extra库添加到您的项目中是值得的。
LocalDate
类表示没有时间且没有时区的仅限日期的值。
LocalDate start = LocalDate.parse( "2017-06-30" );
LocalDate stop = LocalDate.parse( "2017-12-31" );
根据这些,确定ISO 8601日历系统中的年度季度,意味着Q1是1月到3月,Q2是4月到6月,Q3是7月到9月,Q4是10月到12月。
YearQuarter yqStart = YearQuarter.from( start );
YearQuarter yqStop = YearQuarter.from( stop );
将一系列季度收集为List
。
int initialCapacity = ( int ) ( ChronoUnit.YEARS.between( start , stop ) + 1 ) * 4;
List < YearQuarter > quarters = new ArrayList <>( initialCapacity );
每个季度循环,通过调用plusQuarters
递增,并收集到列表中。
YearQuarter yq = yqStart;
while ( ! yq.isAfter( yqStop ) )
{
quarters.add( yq );
// Setup next loop.
yq = yq.plusQuarters( 1 );
}
转储到控制台。
System.out.println( start + "/" + stop + " = " + quarters );
2017-06-30 / 2017-12-31 = [2017-Q2,2017-Q3,2017-Q4]
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。
答案 2 :(得分:2)
我的库Time4J支持使用Java-8的流式API实现非常简单的解决方案:
DateInterval range =
DateInterval.between(
PlainDate.of(2017, 6, 30),
PlainDate.of(2017, 12, 31)
);
range.stream(Duration.of(1, CalendarUnit.QUARTERS))
.map(CalendarQuarter::from)
.forEach(System.out::println);
// 2017-Q2
// 2017-Q3
// 2017-Q4
代码首先构造一个可流传输的date interval。您可以通过迭代地将四分之一年添加到间隔的开始日期来定义流。 map-operation将流中生成的(格里高利)日期映射到Time4J中所需的年度季度,称为CalendarQuarter,最后调用其toString()方法生成输出。
如果您希望消除输出中的连字符,则可以在另一个map方法中应用简单的string-replace-method或使用合适的formatter(最好将其存储在静态常量中它是不可改变的):
ChronoFormatter<CalendarQuarter> f =
ChronoFormatter.ofPattern(
"uuuuQQQ", PatternType.CLDR, Locale.ROOT, CalendarQuarter.chronology());
range.stream(Duration.of(1, CalendarUnit.QUARTERS))
.map(CalendarQuarter::from)
.map(cq -> f.format(cq))
.forEach(System.out::println);
// 2017Q2
// 2017Q3
// 2017Q4
最后一段代码甚至可以通过省略中间类型CalendarQuarter
来简化,因为格里高利日期(此处:PlainDate
)也可以以相同的方式格式化为季度日期(一张地图) - 操作少)。
答案 3 :(得分:1)
这里是使用纯Java 8流和java.time api的解决方案:
public static void main(String[] args) {
LocalDate startDate = LocalDate.of(2000, 12, 25);
LocalDate endDate = LocalDate.of(2002, 4, 1);
Stream<LocalDate> quarterBounds = Stream.iterate(
startDate.with(IsoFields.DAY_OF_QUARTER, 1), date -> date.plus(3, MONTHS));
DateTimeFormatter quarterFormatter =
DateTimeFormatter.ofPattern("uuuuQQQ", Locale.ENGLISH);
quarterBounds
.filter(d -> !endDate.isBefore(d))
.peek(System.out::println)
.map(quarterFormatter::format)
.forEach(System.out::println);
}
样本输出:
2000-10-01
2000Q4
2001-01-01
2001Q1
2001-04-01
2001Q2
2001-07-01
2001Q3
2001-10-01
2001Q4
2002-01-01
2002Q1
2002-04-01
2002Q2
通过How to get the first date and last date of current quarter in java.util.Date。