If you really want to use the dateutils Python library, there is a way. It's a little bit inconvenient but at the end you can use the original and not a copy.
You can use Jython to run the dateutils library. The drawback is, that you cannot directly use the original datutils classes from Java. You have to implement a wrapper Jython class which implements a Java interface.
But first you have to prepare your own custom copy of jython.jar
.
Jython can be used in different ways. The first way is to install Jython similar to Python in its own directory. With this you can use Jython like ordinary Python. You can run Jython scripts, install libraries via setup tools, etc.
The other way is to use the standalone jython.jar
. The standalone jython.jar
contains the whole Jython system. You can run Jython scripts with this JAR, too. But the main purpose to pack the whole Jython system into one JAR is to embed it into a Java application and call Jython/Python code from Java (or vice versa).
The dateutils library isn't part of the Python/Jython standard library. So you cannot use it as is. To create your own jython.jar
you have to first install Jython into its own diretory.
1. Download Jython
Got to the Jython download page and download the 2.5.3 Jython installer JAR. Do not use the higher version numbers with beta status. It is not sure that setup tools will work with these beta versions.
2. Install Jython in a directory
Run java -jar jython-installer-2.5.3.jar
and choose the standard installation type and install it in a directory, e.g. ~/jython2.5.3
.
3. Install setup tools
Download http://peak.telecommunity.com/dist/ez_setup.py and run ~/jython2.5.3/bin/jython ez_setup.py
. See the Jython book appendix A.
4. Install dateutils
library
Download the 1.5 version of dateutils
library: http://labix.org/download/python-dateutil/python-dateutil-1.5.tar.gz. This version is for Python < 3.0.
Unpack the archive and build and install it:
~/jython2.5.3/bin/jython setup.py build
~/jython2.5.3/bin/jython setup.py install
After that your Jython installation should contain the datetuils library at ~/jython2.5.3/Lib/site-packages/python_dateutil-1.5-py2.5.egg/dateutil
.
You can check the installation by running the Jython interpreter and parse an example date string.
~$ ~/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)
>>>
So it works so far. You are now sure that the dateutils library is compatible with Jython.
5. Create the default standalone jython.jar
Run the Jython installer a second time and as installation type choose "Standalone (a callable .jar file)". After that unpack the resulting JAR file (you can use every ZIP unpack tool) in a directory, e.g. ~/jar.
6. Install the dateutils library in jython.jar
My first attempt was to copy the ~/jython2.5.3/Lib/site-packages/python_dateutil-1.5-py2.5.egg
directory to ~/jar/Lib/site-packages
. But this doesn't work in embedded mode. You have to copy ~/jython2.5.3/Lib/site-packages/python_dateutil-1.5-py2.5.egg/dateutil
to ~/jar/Lib
so that the dateutil
directory is directly under ~/jar/Lib
.
7. Create custom jython.jar
Now zip the resulting ~/jar
and name it jython.jar
. Try it by running java -jar jython.jar
. This will start a Jython interpreter from your jython.jar
. Try to parse a date with dateutils.
Now you can include a whole Jython system including the dateutils library into your Java project only by put your custom jython.jar
on the classpath.
8. Create a Java interface
In your Java project create a Java interface. This will work as a bridge between the Java and the Jython world. Later you will create a Jython class implementing this interface. And from Java code you will use this Jython class via this interface.
In this example I call the interface DateutilParser
and put it in the dateutilstest
package.
package dateutiltest;
import java.util.Date;
public interface DateutilParser {
Date parsedate(String s);
}
So the only method accepts a string as parameter and returns a java.util.Date
. Nothing special for the Java side here.
9. Implement the interface with Jython
Create the file MyDateParser.py in the root of your classpath (in Eclipse the root of the src
directory).
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()
At first we import the Java classes Date
and GregorianCalendar
. It is no problem and straight forward to use Java classes within Jython. Then we import our Java interface DateutilParser
. The last import is for the dateutils parser classes. Then we create our Jython class MyDateParser
implementing DateutilParser
. In the parsedate
method we first use the dateutil's parse()
function to create a date out of the string and then convert it via a GregorianCalendar
instance to a java.util.Date
object.
10. Create a MyDateParser instance
The last part in the puzzle is the DateutilParserFactory
Java class, which is responsible to utilize the Jython interpreter to create a MyDateParser
instance and provide access to it via the DateutilParser
interface:
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);
}
}
For details see the Jython book, chapter 10, Using Jython Within Java Applications.
11. Use it
In this example I created a Main
class to demonstrate the functionality:
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));
}
}
And the output is:
2013-11-05