2013-07-17 65 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