2013-07-17 38 views
10

我花了几个小时试图使该下一段代码的工作。创建日期范围斯卡拉,乔达,爪哇

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)) 
} 

我想设置一个日期范围数组,从2000年到2012年以6个月为增量步进。我面临的问题是以下错误。

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$1.<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) 

我似乎是与最后Period.months()部分,但我不知道如何解决它。 Tuple3错误我不知道。

如果有人可以给我一个不同的解决方案,这也将是巨大的。我想要一份2000年至2012年的日期列表,每6个月一次。

任何疑问欢迎。我认为这将是一段常见的代码,但网络上并没有太多关于它的内容。

在此先感谢。

+0

看到这个:http://www.scala-lang.org/node/6982 。您是否在REPL中逐行输入此行?当我用'scalac'编译时,或者当我用'scala'中的代码加载一个文件时,我无法用scala 2.10.0和Joda Time 1.6重现这一点。 – Brian

+0

嗨,布赖恩,我看过那个线程,虽然我不知道该怎么做,除了一些其他人有同样的问题。我正在运行乔达时间1.6,但斯卡拉2.9.2。现在尝试在不同的系统上进行设置。我以前试过scala 2.10.2,虽然我不认为问题在那里。 – Loooit

+1

这个问题可以简化为这个代码片段val dt = new DateTime(2013,7,16)'''''''''''''''''''''''''''''''''''' ' – Brian

回答

12

一个解决办法是这样定义的日期:

val date = new DateTime().withYear(2013).withMonthOfYear(7).withDayOfMonth(16) 

在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) 

另外,我是无法重现此作为在我的评论中指出。似乎REPL和编译器的行为不同。

5

DateTimedoesn't have构造服用三个int参数,所以new DateTime(2012, 06, 30)电话DateTime(Object)构造与元组(2012, 06, 30)作为参数。该文档说:

构造一个代表日期时间的Object实例。

如果对象意味着年表(如GregorianCalendar那样),则该年表将被使用。否则,使用ISO默认值。因此,如果一个GregorianCalendar传递中,所使用GJ的年代,但如果日期是在年表通过将ISO。

的识别出的对象类型在ConverterManager定义和包括ReadableInstantStringCalendarDateString格式由ISODateTimeFormat.dateTimeParser()描述。

不出所料,ConverterManager不知道如何处理一个Scala元组,这导致了异常。

如果有人能给我一个不同的解决方案,那也会很棒。我想要一份2000年至2012年的日期列表,每6个月一次。

如果你确实需要日期,最好使用的类型是LocalDate(它的确有你想要的构造函数)。如果你想在这些日期的开始处使用DateTime,那么你需要考虑使用什么时区。

4

好的,下面是完整的工作代码。

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) 
    }) 

} 
} 

我认为这是没有足够的号码DateTime()功能后(即毫秒等),这意味着该编译器不接受它想要的所有参数我的主要问题。正如Alexey Romanov提到的那样

然后打印所需范围的日期,并且可以用作迭代器。

希望能帮助别人。

感谢@布莱恩和其他人的帮助

4

我需要类似的东西。以下是我想出了:

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 
     } 
    } 
} 

实例应用:

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) 

输出:

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