4

Python 有一个非常方便的包,它可以解析几乎任何明确的日期,并在解析失败时提供有用的错误消息,python-dateutil。与 SimpleDateFormat 类的比较是不利的 - AFAICT SimpleDateFormat 只能处理一种确切的日期格式,并且错误消息没有粒度。

我查看了Joda API,但似乎 Joda 的方式相同 - 一次只能解析一种显式格式。

是否有任何包或库可以重现 python-dateutil 行为?还是我错过了 WRT Joda/SimpleDateFormat 的东西?

4

2 回答 2

2

如果你真的想使用 dateutils Python 库,有办法。这有点不方便,但最后你可以使用原件而不是副本。

您可以使用Jython运行 dateutils 库。缺点是,您不能直接使用 Java 中的原始 datutils 类。您必须实现一个实现 Java 接口的包装器 Jython 类。

但首先您必须准备自己的自定义副本jython.jar

Jython 可以以不同的方式使用。第一种方法是在自己的目录中安装类似于 Python 的 Jython。有了它,您可以像使用普通 Python 一样使用 Jython。您可以运行 Jython 脚本、通过设置工具安装库等。

另一种方法是使用独立的jython.jar. 独立版jython.jar包含整个 Jython 系统。您也可以使用此 JAR 运行 Jython 脚本。但是将整个 Jython 系统打包到一个 JAR 中的主要目的是将其嵌入到 Java 应用程序中并从 Java 调用 Jython/Python 代码(反之亦然)。

dateutils 库不是 Python/Jython 标准库的一部分。所以你不能按原样使用它。要创建您自己的jython.jar,您必须首先将 Jython 安装到它自己的目录中。

1. 下载 Jython 进入Jython 下载页面并下载 2.5.3 Jython 安装程序 JAR。不要使用具有 beta 状态的更高版本号。不确定安装工具是否适用于这些 beta 版本。

2. 将Jython 安装到目录 运行java -jar jython-installer-2.5.3.jar并选择标准安装类型并将其安装在目录中,例如~/jython2.5.3.

3.安装设置工具 下载http://peak.telecommunity.com/dist/ez_setup.py并运行~/jython2.5.3/bin/jython ez_setup.py。请参阅Jython 书籍附录A。

4.安装dateutils 下载1.5版本的dateutils库: http: //labix.org/download/python-dateutil/python-dateutil-1.5.tar.gz。此版本适用于 Python < 3.0。解压缩存档并构建并安装它:

~/jython2.5.3/bin/jython setup.py build
~/jython2.5.3/bin/jython setup.py install

之后,您的 Jython 安装应包含位于~/jython2.5.3/Lib/site-packages/python_dateutil-1.5-py2.5.egg/dateutil.

您可以通过运行 Jython 解释器并解析示例日期字符串来检查安装。

~$ ~/jython2.5.3/bin/jython
Jython 2.5.3 (2.5:c56500f08d34+, Aug 13 2012, 14:48:36) 
[OpenJDK 64-Bit Server VM (Sun Microsystems Inc.)] on java1.6.0_27
Type "help", "copyright", "credits" or "license" for more information.
>>> from dateutil.parser import *
>>> parse('Oct 5, 2013')
datetime.datetime(2013, 10, 5, 0, 0)
>>> 

所以它到目前为止有效。您现在可以确定 dateutils 库与 Jython 兼容。

5. 创建默认的独立 jython.jar 再次运行 Jython 安装程序,并选择“独立(可调用的 .jar 文件)”作为安装类型。之后将生成的 JAR 文件(您可以使用每个 ZIP 解包工具)解压到一个目录中,例如 ~/jar。

6. 在 jython.jar 中安装 dateutils 库 我的第一次尝试是将~/jython2.5.3/Lib/site-packages/python_dateutil-1.5-py2.5.egg目录复制到~/jar/Lib/site-packages. 但这在嵌入式模式下不起作用。您必须复制~/jython2.5.3/Lib/site-packages/python_dateutil-1.5-py2.5.egg/dateutil到,~/jar/Lib以便dateutil目录直接位于~/jar/Lib.

7. 创建自定义 jython.jar 现在将结果压缩~/jar并命名jython.jar。通过运行来尝试java -jar jython.jar。这将从您的jython.jar. 尝试使用 dateutils 解析日期。

现在,您只需将自定义放在类路径中即可将包括 dateutils 库在内的整个 Jython 系统包含到您的 Java 项目jython.jar中。

8. 创建 Java 接口 在您的 Java 项目中创建一个 Java 接口。这将作为 Java 和 Jython 世界之间的桥梁。稍后您将创建一个实现此接口的 Jython 类。从 Java 代码中,您将通过这个接口使用这个 Jython 类。

在此示例中,我调用接口DateutilParser并将其放入dateutilstest包中。

package dateutiltest;

import java.util.Date;

public interface DateutilParser {
  Date parsedate(String s);
}

所以唯一的方法接受一个字符串作为参数并返回一个java.util.Date. 这里的 Java 方面没有什么特别之处。

9. 使用 Jython 实现接口 在类路径的根目录中创建文件 MyDateParser.py(在 Eclipse 中为目录的根src目录)。

import java.util.Date as Date
import java.util.GregorianCalendar as GregorianCalendar
import dateutiltest.DateutilParser as DateutilParser
from dateutil.parser import *


class MyDateParser(DateutilParser):
    def parsedate(self, s):
        d = parse(s)
        g = GregorianCalendar(d.year, d.month, d.day)
        return g.getTime()

首先我们导入 Java 类DateGregorianCalendar. 在 Jython 中使用 Java 类没有问题,而且很直接。然后我们导入我们的 Java 接口DateutilParser。最后一个导入用于 dateutils 解析器类。然后我们创建我们的 Jython 类MyDateParser来实现DateutilParser. 在该parsedate方法中,我们首先使用 dateutil 的parse()函数从字符串中创建日期,然后通过GregorianCalendar实例将其转换为java.util.Date对象。

10. 创建一个 MyDateParser 实例 拼图的最后一部分是DateutilParserFactoryJava 类,它负责利用 Jython 解释器创建一个MyDateParser实例并通过接口提供对它的访问DateutilParser

package dateutiltest;

import org.python.core.PyObject;
import org.python.util.PythonInterpreter;

public class DateutilParserFactory {
  private PyObject parserClass;

  /**
   * Create a new PythonInterpreter object, then use it to
   * execute some python code. In this case, we want to
   * import the python module that we will coerce.
   *
   * Once the module is imported than we obtain a reference to
   * it and assign the reference to a Java variable
   */
  public DateutilParserFactory() {
    final PythonInterpreter interpreter = new PythonInterpreter();
    interpreter.exec("from MyDateParser import MyDateParser");
    parserClass = interpreter.get("MyDateParser");
  }

  /**
   * The create method is responsible for performing the actual
   * coercion of the referenced python module into Java bytecode
   */
  public DateutilParser create() {
    PyObject buildingObject = parserClass.__call__(); 
    return (DateutilParser) buildingObject.__tojava__(DateutilParser.class);
  }
}

有关详细信息,请参阅Jython 书的第 10 章,在 Java 应用程序中使用 Jython

11. 使用它 在这个例子中,我创建了一个Main类来演示功能:

package dateutiltest;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {
  public static void main(String[] args) {
    final DateutilParserFactory fac = new DateutilParserFactory();
    final DateutilParser parser = fac.create();
    final Date d = parser.parsedate("Oct 5, 2013");
    final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    System.out.println(sdf.format(d));
  }
}

输出是:

2013-11-05
于 2013-10-21T21:50:35.153 回答
0

apache-commons-lang 库中有 DateUtils 类,方法:

public static Date parseDate(String str, String[] parsePatterns) throws ParseException

根据JavaDocs

通过尝试各种不同的解析器来解析表示日期的字符串。

解析将依次尝试每个解析模式。仅当解析整个输入字符串时,解析才被视为成功。如果没有匹配的解析模式,则抛出 ParseException。

解析器将对解析的日期宽容。

于 2013-10-21T17:26:46.200 回答