I have the following code. I have stored a utc time in my mySQL db and would like to convert it to local time when I pull it from the database.
Instant startInstant = rs.getTimestamp(5).toInstant();
Instant endInstant = rs.getTimestamp(6).toInstant();
ZoneId z = ZoneId.of(TimeZone.getDefault().getID());
ZonedDateTime start = startInstant.atZone(z);
ZonedDateTime end = startInstant.atZone(z);
System.out.println(start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV")));
System.out.println(end.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV")));
This is the output I get:
2017-11-01 01:40:00 America/Chicago
2017-11-01 01:40:00 America/Chicago
The date and time are the same as in my db: This is the field value in the table:
2017-11-01 01:40:00
The only thing that seems to have updated is just the zoneID to America/Chicago which is functionally useless for what I'm needing.
Any pointers as to where I've gone wrong?
You have not supplied enough information to give an exact Answer. You did not explain exactly the data type of the column around your date-time value. I suspect you did not use the MySQL equivalent to the SQL standard type of TIMESTAMP WITH TIME ZONE.
I also wonder why your example of a stored value lacks any offset-from-UTC or time zone. That is suspicious.
Lastly, you may be looking st your stored value by using an interactive SQL session with a default time zone bring dynamically applied to the value retrieved from the database before displaying in your session. While well-intentioned, I consider this an anti-feature as it masks the true nature of the stored data. This behavior may explain your confusion. Try explicitly setting your session’s default time zone to UTC.
Other issues with your code…
Skip the use of java.sql.Timestamp altogether. If your JDBC driver supports JDBC 4.2 or later, you can work directly with the java.time types.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Do not mix an old legacy class like TimeZone with the modern java.time classes. The legacy classes are completely supplanted by java.time; good riddance.
ZoneId z = ZoneId.systemDefault() ;
You are getting the same value that you have entered in a database.
You have timestamp values in database, but how you can say that the values stored
are in UTC (the values might be in UTC but not in UTC format, so by looking into the value, you can't say that the value is in UTC -> '2017-11-01 01:40:00').
If you want to fetch the value in the different time zone, you can also do like this :
eg:
SET time_zone ='+03:00';
SELECT value
FROM table;
It will be providing you the value in specified time zone.
Related
I save the current date and time of the day in a postgres database with LocalDateTime.now(). The column type is set to TIMESTAMP WITHOUT TIME ZONE. When I access this data, I see that it is 1 hour ahead. I have recorded the date at 15:18, in the database it is 14:18.
I would like this to be the local date so that I can read the dates in the database more easily.
On which side should I correct the problem? On the java side? on the database side? Should I use timezone?
Time zone implicitly applied
Be aware of time zone involvement. Your line with LocalDateTime.now() implicitly applies the JVM’s current default time zone in capturing the current date and current time. Verify the value returned is actually what you expect; do not assume.
so that I can read the dates in the database
How exactly did you read the value stored in the database?
If you executed Java like this:
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
… then you will indeed get back the exact value you stored.
If, on the other hand, you used a tool like psql or pgAdmin, be aware that many such tools have an anti-feature where they inject a current default time zone after retrieval and before returning the value to you. The anti-feature is well-intentioned, but creates a false illusion.
You neglected to describe your exact operations. So I cannot provide a more specific explanation. If you rewrite your Question with details, I may be able to refine my Answer.
Moment
You said:
I save the current date and time of the day in a postgres database with LocalDateTime.now(). The column type is set to TIMESTAMP WITHOUT TIME ZONE
Don’t.
You are using the wrong data types.
You need to change the data type in the database. And you need to change the data type in Java.
I cannot imagine a scenario where calling LocalDateTime.now() is the right thing to do. That class cannot represent a moment, a specific point on the timeline, as the class purposely lacks the context of a time zone or offset from UTC.
To record a moment, define your column as the type TIMESTAMP WITH TIME ZONE. Any time zone or offset info you provide with an input is (a) used to adjust the date and the time to an offset from UTC of zero hours-minutes-seconds, (b) then discarded. So values stored and retrieved from columns of this type are always in UTC.
Capture the current moment in Java. Notice how I passed a specific offset rather than relying implicitly on the JVM’s current default time zone.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
Write to the database in a column of the type TIMESTAMP WITH TIME ZONE.
myPreparedStatement.setObject( … , odt ) ;
Retrieve from the database.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
If need be, adjust to a particular time zone of interest. Same moment, different wall-calendar/clock.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
If using tools other than your own Java code, be aware of their having a time zone injection anti-feature as discussed above. You may want to set the tool’s current default offset/zone to zero, to UTC.
My database is set to default time zone UTC. My Driver should be using system time which I am running my application in a ubuntu container that is set to UTC. I know this because when I call Timezone.getDefault() is returns UTC. So according to my understanding, these times should be close to identical +-1 hour. I am currently in CST. The database time is retrieved with resultset.getTimestamp().getTime(). One (or two) of these numbers are not UTC.
Database time: 1674680930000
System.currentTime(): 1674703050253
Calendar time: 1674703050255
My database is set to default time zone UTC.
Write your Java code in such a way that you don’t care about the current default time zone of the server OS nor the current default time zone of the database session.
Edit your Question to provide actual example code. Then we can critique.
My Driver should be using system time which I am running my application in a ubuntu container that is set to UTC.
No, incorrect. Your JDBC driver is unaware of the host OS’ current default time zone.
What makes you think otherwise? Edit your Question to provide details.
I know this because when I call Timezone.getDefault() is returns UTC.
That code gets the current default time zone of your JVM. Your JVM’s current default time zone may or may not be the same as host OS’ the current default time zone. The two defaults can be set independently of one another.
TimeZone is one of the legacy date-time classes that you should avoid. Use only java.time classes. Never use Dote, Calendar, Timestamp, etc.
To determine your JVM’s current default time zone:
ZoneId z = ZoneId.systemDefault() ;
I am currently in CST.
As I said above, you should write your Java code to avoid depending on any default time zone. Pass optional parameters with your desired/expected time zone.
Record the current moment as seen in UTC.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
Retrieve from database.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Adjust to your desired time zone. CST is not a real time zone. Perhaps you meant America/Chicago.
ZoneId z = ZoneId.of( "America/Chicago" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
The database time is retrieved with resultset.getTimestamp().getTime().
Incorrect. The ResultSet class has no getTimestamp method taking no arguments.
Perhaps you mean to retrieve a date-time value from a column. How to do that depends on the data type of the column.
Edit your Question to document the exact data type of your column, the database engine, and the version.
For MySQL 8:
SQL standard
MySQL
Java
TIMESTAMP WITH TIME ZONE
TIMESTAMP
OffsetDateTime
TIMESTAMP WITHOUT TIME ZONE
DATETIME
LocalDateTime
And search Stack Overflow to learn more. Exchanging date-time values with a database has been covered extensively.
You commented:
So it looks like I missed an important distinction between session and global env variables in MySQL:
Neither of those need be relevant to your Java code for exchanging date-time values with a database.
In our web application we need to show and enter
date time information for different countries in different time zone. Right now, we are maintaining separate web server and separate database (oracle 11g) for each country.
We are planning to merge all into one portal with single database (oracle 11g).
This portal should capture/display date and time in user local time zone.
So far, I have searched about this, I got below suggestion.
1) set web server's and database server's time zone to UTC and while fetching data (data and time) convert into user local time zone.
If you suggest this approach then please clarify the following specific
questions.
most of the time we are capturing date alone, is it require to
capture date and time along with time zone always?
while storing date and time where we need to convert user local time
zone to UTC in javascript/java/oracle?
while fetching date and time where we need to convert UTC to user
local time zone query itself/java/java script?
many place we have reports to show based on date column such as
today/current month/date range.how we can handle this(input - user
local time zone - database in UTC)?
which data type we have to use for date field
(date/timestamp/timestamp with time zone/timestamp with local time
zone)?
2) capture date and time in both user local time zone and UTC. Stored as separate columns, user local time zone will be used for display purpose and UTC will be used for business logic.
If you suggest this approach then please clarify the following specific
questions.
Is it common practice to store the user local time zone and UTC?
which column i have to check condition while fetching reports to show
based on date column such as today/current month/date range?
which data type we have to use for date column
(date/timestamp/timestamp with time zone/timestamp with local time
zone)?
thanks in advance
Read the Question Daylight saving time and time zone best practices. Yours is basically a duplicate.
Servers in UTC
Yes, generally servers should have their OS set to UTC as the time zone, or if not provided use GMT or the Reykjavík Iceland time zone. Your Java implementation probably picks up this setting as its own current default time zone.
Specify time zone
But do not depend on the time zone being set to UTC. A sysadmin could change it. And any Java code in any thread of any app within your JVM can change the JVM’s current default time zone at runtime by calling TimeZone.setDefault. So instead, make a habit of always specifying the desired/expected time zone by passing the optional argument in your Java code.
I consider it a design flaw that any date-time framework would make the time zone optional. Being optional creates endless amounts of confusion because programmers, like everybody else, unconsciously think in terms of their own personal time zone unless prompted. So all too often in date-time work no attention is paid to the issue. Add on the problem that the JVM default varies. By the way, ditto for Locale, same problems, should always be specified explicitly.
UTC
Your business logic, data storage, and data exchange should almost always be done in UTC. Nearly every database has a feature for adjusting any input into UTC and storing in UTC.
When presenting a date-time to a user, adjust into the expected time zone. When serializing a date-time value, use the ISO 8601 string formats. See the Answer by VickyArora for Oracle specifically (I am a Postgres person). Be sure to read the doc carefully, and practice by experimenting to fully understand your database's behavior. The SQL spec does not spell out very much in this regard, and behavior varies widely.
java.sql
Remember that when using Java and JDBC, you will be using the java.sql.Timestamp and related data types. They are always in UTC, automatically. In the future expect to see JDBC drivers updated to directly use the new data types defined in the java.time framework built into Java 8 and later.
java.time
The old classes are outmoded by java.time. Learn to use java.time while avoiding the old java.util.Date/.Calendar and make your programming life much more pleasant.
Until your JDBC driver is updated, you can use the conversion convenience methods built into java.time. See examples next, where Instant is a moment in UTC and ZonedDateTime is an Instant adjusted into a time zone.
Instant instant = myJavaSqlTimestamp.toInstant();
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
To go the other direction.
java.sql.Timestamp myJavaSqlTimestamp = java.sql.Timestamp.from( zdt.toInstant() );
If you need original time zone, store it
If your business requirements consider the original input data’s time zone to be important, to be remembered, then store that explicitly as a separate column in your database table. You can use an offset-from-UTC, but that does not provide full information. A time zone is an offset plus a set of rules for the past, present, and future handling of anomalies such as Daylight Saving Time. So a proper time zone name is most appropriate such as America/Montreal.
Date-only is ambiguous
You said you collect many date-only values, without time-of-day and without time zone. The class for that in java.time is LocalDate. As with LocalTime and LocalDateTime, the “Local…” part means no particular locality, so therefore no time zone, and so not a point on the timeline -- has no real meaning.
Keep in mind that a date-only value is ambiguous by definition. At any given moment, the date varies around the world. For example, just after midnight in Paris France is a new day but in Montréal Québec the date is still “yesterday”.
Usually in business some time zone is implicit, even unconsciously intuited. Unconscious intuition about data points tends not to work well over the long term, especially in software. Better to make explicit what time zone was intended. You could store the intended zone alongside the date such as another column in database table, or your could make a comment in your programming code. I believe it would vastly better and safer to store a date-time value. So how do we transform a date-only into a date-time?
Often a new day is the moment after midnight, the first moment of the day. You might think that means the time-of-day 00:00:00.0 but not always. Daylight Saving Time (DST) and possibly other anomalies may push the first moment to a different wall-clock time. Let java.time determine the correct time-of-day for first moment going through the LocalDate class and its atStartOfDay method.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneId );
ZonedDateTime todayStart = today.atStartOfDay( zoneId );
In some business contexts a new day may be defined (or assumed) to be business hours. For example, say a publisher in New York means 9 AM in their local time when they say “the book draft is due by January 2nd”. Let's get that time-of-day for that date in that time zone.
ZoneId zoneId = ZoneId.of( "America/New_York" );
ZonedDateTime zdt = ZonedDateTime.of( 2016 , 1 , 2 , 9 , 0 , 0 , 0 , zoneId );
What does that mean for the author working in New Zealand? Adjust into her particular time zone for presentation to her by calling withZoneSameInstant.
ZoneId zoneId_Pacific_Auckland = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt_Pacific_Auckland = zdt.withZoneSameInstant( zoneId_Pacific_Auckland );
Database
For database storage we transform into an Instant (a moment on the timeline in UTC) and pass as a java.sql.Timestamp as seen earlier above.
java.sql.Timestamp ts = java.sql.Timestamp.from( zdt.toInstant() );
When retrieved from the database, transform back to a New York date-time. Convert from java.sql.Timestamp to an Instant, then apply a time zone ZoneId to get a ZonedDateTime.
Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "America/New_York" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
If your database driver complies with JDBC 4.2 or later, you may be able to pass/fetch the java.time types directly rather than convert to/from java.sql types. Try the PreparedStatement::setObject and ResultSet::getObject methods.
Use TIMESTAMP WITH LOCAL TIME ZONE
if you want the database to automatically
convert a time between the database and session time zones.
Stores a date and time with up to 9 decimal places of precision. This datatype is
sensitive to time zone differences. Values of this type are automatically converted
between the database time zone and the local (session) time zone. When values are
stored in the database, they are converted to the database time zone, but the local
(session) time zone is not stored. When a value is retrieved from the database, that
value is converted from the database time zone to the local (session) time zone.
Here I have clarified the following specific questions.
Q. Most of the time we are capturing date alone, is it require to capture date and time along with time zone always?
A. Yes
Q. while storing date and time where we need to convert user local time zone to UTC in javascript/java/oracle?
A. Not convert during data save, save as it with source date+time+zone
Q. While fetching date and time where we need to convert UTC to user
local time zone query itself/java/java script?
A. Always convert to display in local time zone OR UTC format where application opened.
Q. Many place we have reports to show based on date column such as
today/current month/date range.how we can handle this(input - user local time zone - database in UTC)?
A. The system should provide setting option to user for date time display in what format, either local where application opened or UTC. All is done on front end only.
Q. Which data type we have to use for date field (date/timestamp/timestamp with time zone/timestamp with local time zone)?
A. Timestamp
So in short, save datetime in source time zone and convert based upon user preferences either in local where page opened or UTC format. Means, conversion will be done through script for display only. The region where product is being popular can also be find.
I would simply transform the existing dates stored in the DB into Long, and persist (ETL process) this Long value, along with the known (or deducted) pattern, Locale and TimeZone (default meta). And persist any new Date as long as with the default meta.
ETL example
Let say 2015-11-29 10:07:49.500 UTC is stored in the DB:
// Known or deducted format of the persisted date
String pattern = "yyyy-MM-dd HH:mm:ss.SSS";
Locale locale = Locale.ENGLISH;
TimeZone zone = "UTC";
// Date to ms
SimpleDateFormat sdf = new SimpleDateFormat(pattern, locale);
sdf.setTimeZone(TimeZone.getTimeZone(zone));
Date date = sdf.parse(pattern);
// ETL: Can now be persisted in Long, along with default META (pattern, Locale, TZ)
Long dateL = date.getTime(); // for e.g. 1448827660720
...
The persisted Long value can also be transformed in any other format, if needed
pattern | locale | tz | result
============================================
yyyy/MM/dd | null | null | 2015/11/29
dd-M-yyyy hh:mm:ss | null | null | 29-11-2015 10:07:40
dd MMMM yyyy zzzz | ENGLISH | null | 29 November 2015 Central European Time
yyyy-MM-dd HH:mm:ss.SSS | null | UTC | 2015-11-29 10:07:49 UTC
Feasible and logical approach is ; Convert user entered time to GMT/UTC +00 and store that in db with or without timezone identifier it does not matter. When you need to display the time to user convert GMT/UTC time in java to local time of user.
You should consider JodaTime and should follow the first suggestion.JodaTime has many classes like LocalDate,LocalDateTime which you can use for your different use cases.
I am searching for an standard SQL way to ensure independently from the database to have a column with a timestamp in UTC or as timestamp with the information of the timezone.
UTC example with stored timestamp UTC in DB-column:
stored UTC value = 2014-01-01 15:30:00.000
local time India 21:00/9pm as local timestamp "2014-01-01 21:00:00.000"
stored UTC value = 2013-12-31 23:30:00.000
local time India 05:00/5am as local timestamp "2014-01-01 05:00:00.000"
In the UTC way the application has to cope with the timezoning
And now the way I do not really know if possible, with timestamp and timezone with the above values
stored local value = 2014-01-01 21:00:00.000
local time India 21:00/9pm as local timestamp "2014-01-01 21:00:00.000"
but there is the timezone information?
or how to get the timezone information of this timestamp?
stored local value = 2014-01-01 05:00:00.000
local time India 05:00/5am as local timestamp "2014-01-01 05:00:00.000"
but there is the timezone information?
or how to get the timezone information of this timestamp?
Hopefully someone can help me out of the dark?
Are there good practices on timezoning issues and storing the data for international application?
tl;dr
To store a moment, a point on the timeline, define a database column of SQL-standard type TIMESTAMP WITH TIME ZONE.
Store a moment in UTC.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
myPreparedStatement.setObject( … , instant ) ;
Retrieve a moment in UTC.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Adjust from UTC to a time zone. Same moment, different wall-clock time.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ; // Specify time zone in proper `Continent/Region` name, never the ambiguous non-standard 3-4 letter pseudo-zone such as `IST` or `PST`.
ZonedDateTime zdt = instant.atZone( z ) ;
Adjust from a time zone to UTC. Same moment, different wall-clock time.
Instant instant = zdt.toInstant() ;
Date-Time Is Not A String
Serious databases do not store date-time values as strings. Do not confuse a string representation generated by either the database or a Java library with the date-time value itself.
Store UTC
Best practice is to use UTC for your database and other storage, as well as the bulk of your business logic. Present in local time zones only as expected by the user.
See Wikipedia for standard date-time types. Even if you do not use Postgres, consult the outstanding documentation on date-time data types. But I do recommend Postgres, for many reasons including its excellent support of date-time.
Use TIMESTAMPZ
This Postgres expert makes the simple and wise recommendation: Always Use TIMESTAMP WITH TIME ZONE
The name of that data type is a misnomer, causing so much confusion. The time zone information is not stored. What it means is that the time zone indicated with incoming data is respected, and the stored value will be adjusted to UTC. Think of TIMESTAMP WITH TIME ZONE as TIMESTAMP WITH RESPECT FOR TIME ZONE. Reread this paragraph three times out loud, then read the above links, and do some experimenting to be sure you understand.
You may want to also store separately the original time zone information. Not for use in your business logic, but for use as logging info for debugging.
Java
As for Java, be sure to avoid the java.util.Date and .Calendar classes. They are notoriously troublesome. They are supplanted in Java 8 by the new java.time package. Use either that package and/or the Joda-Time 2.4 library which inspired java.time.
Time Zone
And in Java always specify the desired time zone. If omitted you'll implicitly be using the JVM's current default time zone. That implicit default means your results will vary across time and space. This is the root cause of much of the trouble in date-time work. If you want UTC, use the constant in Joda-Time, DateTimeZone.UTC.
Ignoring time zones will not make your life easier.
ISO 8601
This standard is extremely useful and sensible. Study the excellent Wikipedia page. Should be your first choice for a String representation.
Search StackOverflow
These issues have been covered on hundreds, if not thousands, of answers.
I have a table which stores both unix time and the equivalent time stamp.
CREATE TABLE tbl_time
(
time_unix BIGINT,
time_timestamp TIMESTAMP WITHOUT TIME ZONE
);
The database is in PostgreSQL. database has been configured with Asia/Tehran time zone.
for example:
1333436817, 2012-04-03 11:36:57
When I convert the unix time into string format in python with:
datetime.datetime.fromtimestamp(1333436817)
it gives me: datetime.datetime(2012, 4, 3, 11, 36, 57) which is correct and equal to database. But when I do this conversion with java using:
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"));
c.setTimeInMillis(1333436817 * 1000);
System.out.println(c.getTime());
It gives: Sat Jan 24 06:12:35 IRST 1970. The system itself is running under Asia/Tehran time zone. I'm using PostgreSQL 8.4.11 on Debian 6.0.5 with python 3.1 and openjdk 6. Can anyone help?
The result of 1333436817 * 1000 is too big for an integer so it overflows. Java will not promote the type for you automatically in this case.
Try that:
c.setTimeInMillis(1333436817 * 1000L);
Notice the L that force your calculation to use long integer.
The Answer by tibo is correct. My additional thoughts follow.
Use TIMESTAMP WITH TIME ZONE
You mentioned using the data type TIMESTAMP WITHOUT TIME ZONE in Postgres. That type is only for a date-time not tied to any specific time zone. For example, "Christmas starts at midnight on December 25, 2015" translates to a different moment in any particular time zone. Christmas starts earlier, for example, in Paris than in Montréal. This data type is rarely appropriate in business apps. See this Postgres expert’s post, Always use TIMESTAMP WITH TIME ZONE.
In Postgres, the other type TIMESTAMP WITH TIME ZONE means "with respect for time zone". Any offset from UTC or time zone information with incoming data is used to adjust to UTC. That accompanying offset or time zone info is then discarded. Some databases preserve this info, but not Postgres.
Your statement:
The database is in PostgreSQL. database has been configured with Asia/Tehran time zone.
…makes no sense. The data type TIMESTAMP WITHOUT TIME ZONE has no time zone (though you may regard it as UTC), and the data type TIMESTAMP WITH TIME ZONE is always in UTC. With regard to storing date-time values, there is no such time zone configuration.
What you may have meant is that the default time zone for a database session is set to Tehran time zone. See the SET TIME ZONE command. But that setting is mere window-dressing, applied when generating a string representation of the date-time value. When using JDBC and the java.sql.Timestamp class, that session setting is irrelevant as no Strings are being generated by Postgres. Your attention to time zones should be on the Java side (see code below) rather than Postgres.
Generally speaking, your host server operating system should be set to UTC. But your app’s code should never depend on that, instead specifying any desired/expected time zone.
java.time
In Java 8 and later, the new java.time package supplants the old java.util.Date/.Calendar classes. These new classes were inspired by Joda-Time library, defined by JSR 310, and extended by the ThreeTen-Extra project.
Eventually JDBC drivers will be updated to directly handle these new types. In the mean time use the conversion methods added to both the old and new classes.
java.sql.Timestamp ts = myResultSet.getTimestamp( 1 );
Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Or given your count of whole seconds from the Unix Time epoch, construct an Instant.
long secondsSinceUnixEpoch = 1_333_436_817L ;
Instant instant = Instant.ofEpochSecond( secondsSinceUnixEpoch );
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
The java Date library has a bad design and not that functional. I can't really help you with your problem but i can give you an advice to try Joda calendar