【问题标题】:java version of python-dateutilpython-dateutil的java版本
【发布时间】:2013-10-18 16:27:40
【问题描述】:

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

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

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

【问题讨论】:

  • 我并不是真的在寻找可以指定多个解析器的解决方案,每种格式一个解析器 - 可能有数百种可能的格式。我正在寻找 python dateutil 类中的功能,您可以在其中提供几乎任何日期字符串并且它只是 Works(TM)。
  • 你在解析什么这么不一致?还是您只是想为每个不同的应用程序使用完全相同的代码行?
  • 不受控制的用户输入。我想让用户输入日期尽可能简单。
  • 然后很遗憾,我什么都没有。如果它是 GUI 或基于 Web 的应用程序,则可能使用日历输入控件将输入内容哄骗为可理解的格式。如果是控制台,我什么都不知道。

标签: java python parsing date datetime


【解决方案1】:

如果你真的想使用 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 download page 并下载 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 book appendix A

4.安装dateutils 下载dateutils库的1.5版本:http://labix.org/download/python-dateutil/python-dateutil-1.5.tar.gz。此版本适用于 Python

~/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 的 datetuils 库。

您可以通过运行 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 启动一个 Jython 解释器。尝试使用 dateutils 解析日期。

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

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 实例 谜题的最后一部分是 DateutilParserFactory Java 类,它负责利用 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 book, chapter 10, Using Jython Within Java Applications

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

【讨论】:

  • 哇,我不想这么说,但我考虑过使用 jython,但因为太笨拙而立即拒绝了。我仍然觉得我不想在我的系统中添加对 jython 和 python 库的依赖,因为它使设置/部署更加困难。话虽如此,无论它是否是我的首选解决方案,这都是一个非常棒的答案,我希望我能再投票给你几次。
  • 是的,将 Jython 添加到项目中只是为了能够使用小型库是一个真正的缺点。我将嵌入式 Jython 用于一个小型内部项目,主要用于作为标准库一部分的出色文本差异实用程序以及 Java 反射过于复杂的一些事情。但我一直想知道,如何在嵌入式中集成第三方 Python 库。所以你的问题让我很好奇。
【解决方案2】:

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

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

根据JavaDocs

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

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

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

【讨论】:

猜你喜欢
  • 2017-04-10
  • 2018-12-30
  • 1970-01-01
  • 1970-01-01
  • 2014-02-13
  • 1970-01-01
  • 1970-01-01
  • 2016-02-27
  • 2014-11-03
相关资源
最近更新 更多