创建 dateRange Scala、Joda、Java
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17690739/
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
Creating a dateRange Scala, Joda, Java
提问by Loooit
I have spent hours trying to make this next piece of code work.
我花了几个小时试图让下一段代码工作。
import org.joda.time.{DateTime, Period}
def dateRange(from: DateTime, to: DateTime, step: Period): Iterator[DateTime] =Iterator.iterate(from)(_.plus(step)).takeWhile(!_.isAfter(to))
val range = {
dateRange(new DateTime(2012, 06, 30).minusYears(5), new DateTime(2000, 06, 30),new Period.months(6))
}
I'm trying to set up a date range array that steps through from 2000 to 2012 in 6 month increments. The problem that I am facing is the following error.
我正在尝试设置一个日期范围数组,该数组以 6 个月为增量从 2000 年到 2012 年。我面临的问题是以下错误。
Exception in thread "main" java.lang.IllegalArgumentException: No instant converter found for type: scala.Tuple3
at org.joda.time.convert.ConverterManager.getInstantConverter(ConverterManager.java:165)
at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:169)
at org.joda.time.DateTime.<init>(DateTime.java:241)
at tester.MomentumAlgo$class.$init$(MomentumAlgo.scala:154)
at tester.RunMomentumAlgo$$anon.<init>(RunMomentumAlgo.scala:86)
at tester.RunMomentumAlgo$.main(RunMomentumAlgo.scala:86)
at tester.RunMomentumAlgo.main(RunMomentumAlgo.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
I seems to be something to do with the last Period.months() part, however I have no idea how to fix it. The Tuple3 error I have no idea about.
我似乎与上一个 Period.months() 部分有关,但是我不知道如何解决它。我不知道 Tuple3 错误。
If someone can give me a different solution, that would also be great. I want a list of dates from 2000 to 2012, every 6 months.
如果有人能给我一个不同的解决方案,那也很棒。我想要一个从 2000 年到 2012 年的日期列表,每 6 个月一次。
Any questions welcome. I thought this would be a common piece of code, but there isn't much on the net about it.
欢迎任何问题。我认为这将是一段常见的代码,但网上关于它的内容并不多。
Thanks in advance.
提前致谢。
回答by Brian
A work around is to define the dates like this:
解决方法是定义这样的日期:
val date = new DateTime().withYear(2013).withMonthOfYear(7).withDayOfMonth(16)
The entire sequence in the REPL then becomes this:
REPL 中的整个序列然后变成这样:
scala> import org.joda.time.{DateTime, Period}
import org.joda.time.{DateTime, Period}
scala> def dateRange(from: DateTime, to: DateTime, step: Period): Iterator[DateTime] =Iterator.iterate(from)(_.plus(step)).takeWhile(!_.isAfter(to))
dateRange: (from: org.joda.time.DateTime, to: org.joda.time.DateTime, step: org.joda.time.Period)Iterator[org.joda.time.DateTime]
scala> val from = new DateTime().withYear(2012).withMonthOfYear(6).withDayOfMonth(30).minusYears(5)
from: org.joda.time.DateTime = 2007-06-30T21:46:05.536-07:00
scala> val to = new DateTime().withYear(2000).withMonthOfYear(6).withDayOfMonth(30)
to: org.joda.time.DateTime = 2000-06-30T21:46:26.186-07:00
scala> val range = dateRange(from, to, new Period().withMonths(6))
range: Iterator[org.joda.time.DateTime] = non-empty iterator
scala> range.toList
res4: List[org.joda.time.DateTime] = List(
2000-06-30T21:46:26.186-07:00,
2000-12-30T21:46:26.186-08:00,
2001-06-30T21:46:26.186-07:00,
2001-12-30T21:46:26.186-08:00,
2002-06-30T21:46:26.186-07:00,
2002-12-30T21:46:26.186-08:00,
2003-06-30T21:46:26.186-07:00,
2003-12-30T21:46:26.186-08:00,
2004-06-30T21:46:26.186-07:00,
2004-12-30T21:46:26.186-08:00,
2005-06-30T21:46:26.186-07:00,
2005-12-30T21:46:26.186-08:00,
2006-06-30T21:46:26.186-07:00,
2006-12-30T21:46:26.186-08:00)
Also, I wasn't able to reproduce this as noted in my comment. Seems the behavior is different in the REPL and the compiler.
此外,如我的评论中所述,我无法重现这一点。似乎 REPL 和编译器中的行为不同。
回答by Alexey Romanov
DateTimedoesn't havea constructor taking three intarguments, so new DateTime(2012, 06, 30)calls DateTime(Object)constructor with the tuple (2012, 06, 30)as the argument. The documentation says:
DateTime没有带三个int参数的构造函数,所以用元组作为参数new DateTime(2012, 06, 30)调用DateTime(Object)构造(2012, 06, 30)函数。文档说:
Constructs an instance from an
Objectthat represents a datetime.If the object implies a chronology (such as
GregorianCalendardoes), then that chronology will be used. Otherwise, ISO default is used. Thus if aGregorianCalendaris passed in, the chronology used will be GJ, but if a Date is passed in the chronology will be ISO.The recognised object types are defined in
ConverterManagerand includeReadableInstant,String,CalendarandDate. TheStringformats are described byISODateTimeFormat.dateTimeParser().
从
Object表示日期时间的构造一个实例。如果对象暗示了一个年表(例如
GregorianCalendar确实如此),那么将使用该年表。否则,将使用 ISO 默认值。因此,如果GregorianCalendar传入a ,则使用的年表将是 GJ,但如果在年表中传递日期将是 ISO。识别出的对象类型中所定义
ConverterManager的,包括ReadableInstant,String,Calendar和Date。该String格式由所描述ISODateTimeFormat.dateTimeParser()。
Unsurprisingly, ConverterManagerdoesn't know what to do with a Scala tuple, which results in the exception.
不出所料,ConverterManager不知道如何处理 Scala 元组,从而导致异常。
If someone can give me a different solution, that would also be great. I want a list of dates from 2000 to 2012, every 6 months.
如果有人能给我一个不同的解决方案,那也很棒。我想要一个从 2000 年到 2012 年的日期列表,每 6 个月一次。
If you actually want dates, the better type to use is LocalDate(which does have the constructor you want, by the way). If you want DateTimeat the start of these dates, then you need to think about what time zone to use.
如果你真的想要日期,最好使用的类型是LocalDate(顺便说一下,它确实有你想要的构造函数)。如果您想DateTime在这些日期的开始,那么您需要考虑使用哪个时区。
回答by Loooit
Ok, Here is the complete working code.
好的,这是完整的工作代码。
import org.joda.time.{Period, DateTime}
object runme {
def main(args:Array[String]) {
def dateRange(from: DateTime, to: DateTime, step: Period): Iterator[DateTime]
=Iterator.iterate(from)(_.plus(step)).takeWhile(!_.isAfter(to))
val range = { dateRange(new DateTime(2000, 06, 30,0,0,0,0).minusYears(5) ,new DateTime(2013, 06, 30,0,0,0,0),new Period(0,6,0,0,0,0,0,0))}
range.foreach(u => {
print(u.getYear)
print(u.getMonthOfYear)
println(u.getDayOfMonth)
})
}
}
I think my main problem was not having enough numbers after the DateTime()functions (ie the milliseconds etc.) this meant the compiler wasn't receiving all the parameters that it wanted. As mentioned by Alexey Romanov
我认为我的主要问题是DateTime()函数后面没有足够的数字(即毫秒等),这意味着编译器没有收到它想要的所有参数。正如阿列克谢·罗曼诺夫所说
This then prints the dates for a desired range, and can be used as an iterator.
然后打印所需范围的日期,并可用作迭代器。
Hope that helps others.
希望能帮助别人。
Thanks @Brian and others for the Help
感谢@Brian 和其他人的帮助
回答by Brandon Kearby
I was needing something similar. Here's what I came up with:
我需要类似的东西。这是我想出的:
import org.joda.time.{Period, DateTime}
class DateRange(val start: DateTime, val end: DateTime, val step: Period, inclusive: Boolean) extends Iterable[DateTime] {
override def iterator: Iterator[DateTime] = new DateRangeIterator
class DateRangeIterator extends Iterator[DateTime] {
var current = start
override def hasNext: Boolean = current.isBefore(end) || (inclusive && current == end)
override def next(): DateTime = {
val returnVal = current
current = current.withPeriodAdded(step, 1)
returnVal
}
}
}
Example Usage:
示例用法:
val startOfDay: DateTime = new DateTime().withTimeAtStartOfDay()
val endOfDay: DateTime = startOfDay.plusDays(1)
val dateRange = new DateRange(startOfDay, endOfDay, Period.hours(1), false)
for (d <- dateRange) println(d)
Output:
输出:
2015-03-16T00:00:00.000-05:00
2015-03-16T01:00:00.000-05:00
2015-03-16T02:00:00.000-05:00
2015-03-16T03:00:00.000-05:00
2015-03-16T04:00:00.000-05:00
2015-03-16T05:00:00.000-05:00
2015-03-16T06:00:00.000-05:00
2015-03-16T07:00:00.000-05:00
2015-03-16T08:00:00.000-05:00
2015-03-16T09:00:00.000-05:00
2015-03-16T10:00:00.000-05:00
2015-03-16T11:00:00.000-05:00
2015-03-16T12:00:00.000-05:00
2015-03-16T13:00:00.000-05:00
2015-03-16T14:00:00.000-05:00
2015-03-16T15:00:00.000-05:00
2015-03-16T16:00:00.000-05:00
2015-03-16T17:00:00.000-05:00
2015-03-16T18:00:00.000-05:00
2015-03-16T19:00:00.000-05:00
2015-03-16T20:00:00.000-05:00
2015-03-16T21:00:00.000-05:00
2015-03-16T22:00:00.000-05:00
2015-03-16T23:00:00.000-05:00
回答by hucko
I just stumbled upon this problem and came up with this simple solution.
我偶然发现了这个问题并想出了这个简单的解决方案。
def generateDateRange(from: LocalDate, to: LocalDate): List[Date] = {
if(from.compareTo(to) > 0) Nil
from :: generateDateRange(from.plusDays(1), to)
}
We recursively build a list of dates by prepending the start of the range to the new range which starts a day later.
我们通过将范围的开始添加到一天后开始的新范围来递归地构建日期列表。

