2

我正在为外部工具的命令行界面编写解析器,并且正在使用 Scala 的解析器组合器库。作为其中的一部分,我需要解析格式EEE MMM d HH:mm:ss yyyy Z的标准日期。

Scala 的解析器组合器是“基于流的”,可以使用 CharSequence 而不是字符串。这让我很难使用JodaTime 中的java.text.DateTimeFormatDateTimeFormat,因为它们都使用字符串。

到目前为止,我不得不像这样编写自己的正则表达式解析器来解析日期,但我更愿意将使用 JodaTime 完成的工作合并到我的解析器中。我真的不想重新发明轮子。我一直在查看 JodaTime 的源代码,但我不确定为什么它需要使用 Strings 而不仅仅是 CharSequences。我是否缺少某些方面?

4

3 回答 3

1

现在明白了。好的,有一个比分叉更简单的解决方案。这里:

trait DateParsers extends RegexParsers {
  def dateTime(pattern: String): Parser[DateTime] = new Parser[DateTime] {
    val dateFormat = DateTimeFormat.forPattern(pattern);

    def jodaParse(text: CharSequence, offset: Int) = {
      val mutableDateTime = new MutableDateTime
      val maxInput = text.source.subSequence(offset, dateFormat.estimateParsedLength + offset).toString
      val newPos = dateFormat.parseInto(mutableDateTime, maxInput, 0)
      (mutableDateTime.toDateTime, newPos + offset)
    }

    def apply(in: Input) = {
      val source = in.source
      val offset = in.offset
      val start = handleWhiteSpace(source, offset)
      val (dateTime, endPos) = jodaParse(source, start)
      if (endPos >= 0)
        Success(dateTime, in.drop(endPos - offset))
      else
        Failure("Failed to parse date", in.drop(start - offset))
    }
  }
}
于 2011-02-03T14:20:36.850 回答
0

I'm not sure what you are asking. Are you asking why RegexParser.parse()'s in parameter takes a CharSequence? If so there's another overloaded RegexParser.parse() that takes a Reader, which you can write a simple conversion function like so:

def stringToReader(str: String): Reader = new StringReader(str)

As to the date format, I find it perfectly fine to define it as a token in the parser.

Hope this helps.

于 2011-02-03T14:37:14.050 回答
0

这是我现在的解决方案:

我分叉了 joda-time 并对其进行了一些小改动以使其在CharSequences 而不是Strings 上工作。在这里https://github.com/hedefalk/joda-time/commit/ef3bdafd89b334fb052ce0dd192613683b3486a4

然后我可以这样写DateParser

trait DateParsers extends RegexParsers {
  def dateTime(pattern: String): Parser[DateTime] = new Parser[DateTime] {
    val dateFormat = DateTimeFormat.forPattern(pattern);

    def jodaParse(text: CharSequence, offset: Int) = {
      val mutableDateTime = new MutableDateTime
      val newPos = dateFormat.parseInto(mutableDateTime, text, offset)
      (mutableDateTime.toDateTime, newPos)
    }

    def apply(in: Input) = {
      val source = in.source
      val offset = in.offset
      val start = handleWhiteSpace(source, offset)
      val (dateTime, endPos) = jodaParse(source, start)
      if (endPos >= 0)
        Success(dateTime, in.drop(endPos - offset))
      else
        Failure("Failed to parse date", in.drop(start - offset))
    }
  }
}

然后我可以使用这个特征来制定生产规则,例如:

private[this] def dateRow = "date:" ~> dateTime("EEE MMM d HH:mm:ss yyyy Z")

我是不是工作过度了?我现在真的很累……</p>

于 2011-02-03T14:45:44.810 回答