Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am totally out of my depth here. I have this pseudo code that I would like to write in Java but have no idea where to start. The following is the logic that I would like to express. Any advice would be much appreciated.
if(bestBeforeDate <= today() + 2days) // if a product is two days before its best before date
toShipOut = false;
else if (bestBeforeDate >= today >= bbDate- 8 days) // from 8 days before best before day
DiscountedPrice();
else
toShipOut = true;
Use Calendar.add() to add number of days. You need to have a temporary Calendar for each additions.
Calendar c = Calendar.getInstance();
c.setTime(new Date()); // Current date
c.add(Calendar.DATE, 2); // Adding 2 days
Check Out Date.
Notice the constructor Date(int year, int month, int date)
Also notice the boolean method after(Date when)
You should be able to find everything you need there.
GregorionCalendar is usually preferred to Date now, but it is the same concept.
GregorianCalendar(int year, int month, int dayOfMonth)
public int compareTo(Calendar anotherCalendar)
Beware of Date/Calendar Classes
Caution: The java.util.Date/Calendar classes bundled with Java are notoriously bad. Instead, use the third-party library Joda-Time, or in Java 8 use the new JSR 310 features (inspired by Joda-Time).
Considerations
Think about time as well as date. And time zones. Generally it is best to store and work with UTC time (no time zone offset), then convert to zoned date-time for presentation to user.
Example Code
I'm not promising this source code example is logically consistent, but it will put you in the right direction. Joda-Time 2.3 on Java 7 on a Mac.
The boolean logic in your pseudo-code is flawed, so I ignored that aspect. I focused on the date-time angle.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
DateTimeZone denverTimeZone = DateTimeZone.forID( "America/Denver" );
// In real world, get 'bestBeforeDate' from storage. Stored in UTC.
// Call 'withTimeAtStartOfDay' method rather than try to set midnight. Not every day in every time zone has a midnight.
// For this example, we'll hard-code bestBeforeDate to first moment of day Nov 1 in Denver. Then convert to UTC.
DateTime bestBeforeDate = new DateTime( 2013, DateTimeConstants.NOVEMBER, 1, 3, 3, denverTimeZone ).withTimeAtStartOfDay().toDateTime( DateTimeZone.UTC );
DateTime now = new DateTime().toDateTime( DateTimeZone.UTC );
DateTime twoDaysFromNow = now.plusDays( 2 );
if ( bestBeforeDate.isBefore( twoDaysFromNow ) ) {
// Do something
} else {
// Do something else.
}
System.out.println( "bestBeforeDate: " + bestBeforeDate );
System.out.println( "now: " + now );
System.out.println( "twoDaysFromNow: " + twoDaysFromNow );
When run…
bestBeforeDate: 2013-11-01T06:00:00.000Z
now: 2013-12-03T04:54:55.405Z
twoDaysFromNow: 2013-12-05T04:54:55.405Z
Related
I was looking to do a simple script of setting a time every 10minutes on Oct 26th 2020.
My loop looks like below.
However even though the time generally seems right when i output 'time' var, then i convert it to Date object and do a toString() on that 'd' variable then it seems to convert it to another time. If you want to see it run on an online java compiler you can see it in action here:
https://ideone.com/T8anod
You can see it do strange stuff like:
0:00 AM
Mon Oct 26 10:00:00 GMT 2020
0:10 AM
Mon Oct 26 10:10:00 GMT 2020
...
12:00 PM
Mon Oct 26 22:00:00 GMT 2020
12:10 PM
...
Mon Oct 26 22:10:00 GMT 2020
One unusually thing is i'll set a breakpoint in my IDE at 12 hours... and if I debug slowly it will set the correct time. Then i'll remove my breakpoint and play through the rest of the script and the times then end up incorrect again. Very unusual behavior I haven't seen in Java yet.
I could do something like this to reset the hours (or use a different technique):
Date d = cal.getTime();
d.setHours(hour); //deprecated
But I'd rather just figure out for now why Java is acting this way.
for(int hour=0; hour < 24; hour++ ) {
for(int minute = 0; minute < 6; minute++) {
String str_min = minute==0 ? "00" : String.valueOf(minute*10);
String time = String.valueOf( hour > 12 ? hour-12 : hour) +":"+ str_min +" "+ ((hour >= 12 ? Calendar.PM : Calendar.AM)==1 ? "PM" : "AM");
//note: got lazy and not outputting "00" for hour
System.out.println( time );
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 9); //Oct=9
cal.set(Calendar.DAY_OF_MONTH, 26);
cal.set(Calendar.YEAR, 2020);
cal.set(Calendar.HOUR_OF_DAY, hour );
cal.set(Calendar.MINUTE, minute*10 ); //0=0, 1=10, ... 5=50
cal.set(Calendar.AM_PM, (hour >= 12 ? Calendar.PM : Calendar.AM) );
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date d = cal.getTime();
System.out.println( d.toString() );
}
}
java.util.Date is a lie. It does not represent a date; it represents an instant in time, it has no idea about timezones, or this concept of 'hours'. That's why everything (except the epoch-millis-based methods and constructors) are marked deprecated.
The calendar API tries to fix this, but is a horrible, horrible API.
Use java.time instead. The ugly API goes away, and unlike the old stuff, you have types that actually represent exactly what you want. Given that you aren't messing with timezones here, you want LocalDateTime:
for (int hour = 0; hour < 24; hour++) {
for (int minute = 0; minute < 60; minute += 10) {
LocalDateTime ldt = LocalDateTime.of(2020, 10, 26, hour, minute, 0);
System.out.println(ldt);
// or better:
System.out.println(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(ldt));
}
}
Note how October is '10' in this API, because this API is not insane, for example. You can use any of the many predefined formatters in DTF, or write your own with a pattern to control precisely how you want to render the date.
If you want to represent other things, you can do so; ZonedDateTime for a specific time the way humans would say it (say: I have an appointment with the dentist, who is in Rome, at a quarter past 2 in the afternoon on november 2nd, 2020). The point of such a concept is this: If Rome decides to switch timezones, then the actual instant in time your appointment occurs should change along with it.
If you want an instant in time, there's Instant. This is a specific moment in time (in the past or future) that will not change in terms of how many milliseconds remain until it occurs. Even in the face of countries changing their zone.
And LDT is, well, LDT: It just represents a year, a month, a day, hours, minutes, and seconds - without a timezone.
tl;dr
LocalDate
.now( ZoneId.of( "America/Chicago" ) ) // Today
.atStartOfDay( ZoneId.of( "America/Chicago" ) ) // First moment of today. Returns a `ZonedDateTime` object.
.plus(
Duration.ofMinutes( 10 ) // Ten minutes later.
) // Returns another `ZonedDateTime` object.
Avoid legacy date-time classes
You are using terrible date-time classes that were supplanted years ago by the java.time classes. Sun, Oracle, and the JCP gave up on those classes, and so should you.
Rather than try to understand those awful classes, I suggest you invest your effort in learning java.time.
Use java.time
Much easier to capture a Instant object when you want the current date-time moment.
Note that java.time uses immutable objects. Rather than alter an existing object, we generate a fresh one.
To represent a moment for every ten-minute interval of today:
ZoneId z = ZoneId.of( "Africa/Tunis" ) ; // Or "America/New_York", etc.
LocalDate today = LocalDate.now( z ) ;
Your code makes incorrect assumptions. Days or not always 24 hours long. They may be 23 hours, 25 hours, or some other length. Also not every day in every time zone starts at 00:00. Let java.time determine the first moment of the day.
ZonedDateTime start = today.atStartOfDay( z ) ;
Get the start of the next day.
ZonedDateTime stop = start.plusDays( 1 ) ;
Loop for your 10-minute chunk of time. Represent that chunk as a Duration.
Duration d = Duration.ofMinutes( 10 ) ;
List< ZonedDateTime > results = new ArrayList<>() ;
ZonedDateTime zdt = start ;
while( zdt.isBefore( stop ) )
{
results.add( zdt ) ;
zdt = zdt.plus( d ) ;
}
See this code run live at IdeOne.com.
Strings
You can generate strings in any format to represent the content of those ZonedDateTime objects. You can even let java.time automatically localize.
Locale locale = Locale.CANADA_FRENCH ; // Or Locale.US etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale ) ;
String output = myZonedDateTime.format( f ) ;
In particular, Locale.US and FormatStyle.MEDIUM might work for you. Fork the code at IdeOne.com to experiment.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
The other answers tell you to use a different API, i.e. to not use Calendar, and they are right, but they don't tell you why the question code doesn't work.
If you read the documentation of Calendar, and look for section "Calendar Fields Resolution", you will find (bold highlight by me):
Calendar Fields Resolution
When computing a date and time from the calendar fields, there may be insufficient information for the computation (such as only year and month with no day of month), or there may be inconsistent information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15, 1996 is actually a Monday). Calendar will resolve calendar field values to determine the date and time in the following way.
If there is any conflict in calendar field values, Calendar gives priorities to calendar fields that have been set more recently. The following are the default combinations of the calendar fields. The most recent combination, as determined by the most recently set single field, will be used.
For the date fields:
YEAR + MONTH + DAY_OF_MONTH
YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
YEAR + DAY_OF_YEAR
YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
For the time of day fields:
HOUR_OF_DAY
AM_PM + HOUR
The question code has:
cal.set(Calendar.HOUR_OF_DAY, hour );
cal.set(Calendar.AM_PM, (hour >= 12 ? Calendar.PM : Calendar.AM) );
Since the last of those fields set is AM_PM, it resolved the hour using AM_PM + HOUR, and since you never call clear() and never set HOUR, the value is the 12-hour clock value set by the getInstance() call, i.e. the current time.
You have 2 choices to fix this:
// Only set the 24-hour value
cal.set(Calendar.HOUR_OF_DAY, hour);
// Set the 12-hour value
cal.set(Calendar.HOUR, hour % 12);
cal.set(Calendar.AM_PM, (hour >= 12 ? Calendar.PM : Calendar.AM) );
I would recommend doing the first one.
I would also highly recommend calling clear() before setting fields, so the result is not polluted by left-over values. That would eliminate the need to set SECOND and MILLISECOND to 0.
Actually, I would recommend using the newer Time API, like the other answers do, but at least you now know why the code was failing.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am trying to get the date and time value from a Date method in the java.time.LocalDateTimeclass. I have stored that value in a variable and I want to use it to set the parameter for an SQL query, but I am unable to extract the value. The code won't compile. I tried this:
LocalDateTime dt = LocalDateTime.now();
query.setParameter("test", Date.valueOf(dt)); //error thrown here. I want to extract the current date and time ( hours, minutes, seconds) value stored in the dt variable
There is no Date.valueOf(LocalDateTime), there is only Date.valueOf(LocalDate).
You need to use LocalDate directly or you can convert the LocalDateTime to LocalDate by calling toLocalDate on it.
Notice that java.sql.Date is actually not used for representing time-components like hours, minutes, seconds and so on. If you want both (date and time), then use java.sql.Timestamp, which even has the method that you want: Timestamp.valueOf(LocalDateTime).
Just a side note: The class for time-only is java.sql.Time.
You should be using a plain java.time solution without any relation to the outdated API around java.util.Date. Date.valueOf(LocalDate) just exists to make legacy code compatible with the modern datetime API (that is java.time).
Since you haven't clarified which time your question is about, I can just show different possibilities.
Please note that LocalDateTime is not suitable for catching timestamps because it does not contain information about your time zone or an offset, but you can add one if necessary:
public static void main(String[] args) {
// get "now" without any time zone or offset information
LocalDateTime now = LocalDateTime.now();
// extract the date part
LocalDate today = now.toLocalDate();
// extract the time-of-day part
LocalTime timeOfNow = now.toLocalTime();
// then print the single parts (date and time of day)
System.out.println("Today is " + today + " and now is " + timeOfNow + " that day");
// print the full timestamp
System.out.println("Full date and time are now " + now);
// or print the epoch milliseconds (A ZONE OR AN OFFSET IS NEEDED THEN)
System.out.println("Moment in time of now is "
+ now.toInstant(ZoneOffset.UTC).toEpochMilli() + " in UTC");
}
The output of this is (see the output for execution time ;-) )
Today is 2020-08-13 and now is 15:04:46.728 that day
Full date and time are now 2020-08-13T15:04:46.728
Moment in time of now is 1597331086728 in UTC
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am working on Selenium Java, I need to get the following date format without the time, as a string in selenium java to validate whether it is up to date with the published date. I used getText() method from the website by splitting from the time and date. Is there any other best ways rather than this solution!
java.time
Edit: I have added more explanation and more code lines.
There’s a little challenge in the fact that the string on the website does not include year. One simple way to handle it is:
ZoneId websiteTimeZone = ZoneId.of("America/Lower_Princes");
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("dd-MMM HH:mm", Locale.ENGLISH);
String stringFromWebsite = "06-Feb 06:37";
MonthDay today = MonthDay.now(websiteTimeZone);
System.out.println("Today is " + today);
MonthDay date = MonthDay.parse(stringFromWebsite, formatter);
System.out.println("Date from website is " + date);
if (date.equals(today)) {
System.out.println("It’s up to date");
} else {
System.out.println("It’s *NOT* up to date");
}
When I ran today (March 12), the snippet printed:
Today is --03-12
Date from website is --02-06
It’s *NOT* up to date
A MonthDay is a month and day of month without year. The advantage of using this class is we don’t need concern ourselves with year. A possible drawback is we can’t compare two such objects determine which one is before or after the other one. Such a comparison would require knowing the year of each one.
We need to know the time zone that the website uses since it is never the same date everywhere on Earth. Please insert the correct one where I put America/Lower_Princes.
I am parsing the string from the website into a MonthDay using a DateTimeFormatter with format pattern dd-MMM HH:mm since lower case d is for day of month, M is for month, H for hour of day and lower case m for minut of the hour. Since I am parsing into a MonthDay, the time is ignored (only its syntax still checked). In the print --03-12 means March 12 and --02-06 similarly February 6 (the date from the website). Since they are not the same, the code prints that the website is not up to date.
A more advanced solution might check if the date is a few days before or after today’s date and/or also look at the time.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Stack Overflow question How do I simply parse a date without a year specified?
You can use selenium's getText(), in order to acquire the value as a String.
Afterwards you can use Java's DateTimeFormatter, to parse this date, and transform it to the format you want
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I need to schedule tasks based on times and days the user inputs. These tasks repeat every week, and based on checkbox values I need to set them enabled on those days.
For example, it's Wednesday the sixth 15:40 UTC+2 at the moment. If the user wants to schedule a task every Wednesday at 12:00, I want to get the time in milliseconds on the thirteenth of November at 12:00. If the task is set to be scheduled at 16:00 every Wednesday, I want the time today. Task scheduled to run on every Thursday results in the millisecond representation of tomorrow. So, basically the closest date that is coming. How do I implement this in Java?
The deprecated Date.getDay() function explains how to do this using Calendar. (Date still works if you really want to use it despite being deprecated).
Calendar.get(Calendar.DAY_OF_WEEK);
Process-wise, you would have a class for storing the event's day of a week as an int, and the time.
Then, you would evaluate today's date and time for the following:
Evaluate whether or not today is the specified day of the week.
If it is, check whether or not the time has already passed.
If it hasn't, schedule it logically for today at that time.
If it has, add 7 days to the calendar date to get the expected date.
Otherwise, if the scheduled day of the week is before today's day of the week:
Subtract the difference between the two days from 7. (i.e. if target day is Sunday (0) and today is Wednesday (3), 7 - (3 - 0) = 4, therefore add 4 days to today's date to get target date)
If it's after, just calculate the difference between the two days (i.e. if the target day is Saturday (6) and today is Wednesday (3), 6 - 3 = 3, therefore add 3 days to today's date to get the target date).
You may also need to check for DST.
The simplest, and maybe cheekiest, answer is to use Quartz. :)
http://quartz-scheduler.org/
You can of course write your own scheduler, but this is not a trivial task.
Edit
To get the date, you can use the add() method on the calendar.
To get the time in ms, you can use the method getTimeInMillis().
If you want a much easier (and in my humble opinion, much more intuitive) approach you can use the DateTime class from joda-time ( http://www.joda.org/joda-time/ ) which are more elegant, immutable and timezone aware. :)
Good luck.
Thanks for answering. Compass' answer was correct and I created the following implementation in Java:
public static long nextDate(int day, int hour, int minute) {
// Initialize the Calendar objects
Calendar current = Calendar.getInstance();
Calendar target = Calendar.getInstance();
// Fetch the current day of the week.
// Calendar class weekday indexing starts at 1 for Sunday, 2 for Monday etc.
// Change it to start from zero on Monday continueing to six for Sunday
int today = target.get(Calendar.DAY_OF_WEEK) - 2;
if(today == -1) today = 7;
int difference = -1;
if(today <= day) {
// Target date is this week
difference = day - today;
} else {
// Target date is passed already this week.
// Let's get the date next week
difference = 7 - today + day;
}
// Setting the target hour and minute
target.set(Calendar.HOUR_OF_DAY, hour);
target.set(Calendar.MINUTE, minute);
target.set(Calendar.SECOND, 0);
// If difference == 0 (target day is this day), let's check that the time isn't passed today.
// If it has, set difference = 7 to get the date next week
if(difference == 0 && current.getTimeInMillis() > target.getTimeInMillis()) {
difference = 7;
}
// Adding the days to the target Calendar object
target.add(Calendar.DATE, difference);
// Just for debug
System.out.println(target.getTime());
// Return the next suitable datetime in milliseconds
return target.getTimeInMillis();
}
I find it funny that Java (or the java.util library) does not have a built-in function to calculate difference in dates. I want to subtract one date from another to get the elapsed time between them. What is the best way to do this?
I know the simple way is to take the difference of the time in milliseconds and then convert that into days. However, I wanted to know if this works in all cases (with daylight saving, etc.).
Java's not missing much, if you look at open source: try Joda-Time.
I know the simple way is to take the
difference of the time in milliseconds
and then convert that into days.
However, i wanted to know if this
works in all cases (with daylight
saving, etc.).
If your times are derived from UTC dates, or they are just the difference between two calls to System.getCurrentTimeMillis() measured on the same system, you will get a valid number of milliseconds as the difference, independent of any timezone issues. (which is why everything should be using UTC as a storage format -- it's much easier to go from UTC->local time; if you try to go the other way then you need to store the local timezone along with the local time -- or attempt to infer it, gack!)
As for turning this into a number of days, you should just be able to divide by 86400000... with the caveat that there is an occasional leap second every other year or so.
Use either Joda-Time or the new java.time package in Java 8.
Both frameworks use the Half-Open approach where the beginning is inclusive while the ending is exclusive. Sometimes notated as [). This is generally the best approach for defining spans of time.
java.time
The java.time framework built into Java 8 and later has a Period class to represent a span of time as a number of years, a number of months, and a number of days. But this class is limited to whole days, no representation of hours, minutes, and seconds.
Note that we specify a time zone, crucial for determining a date. For example, a new day dawns earlier in Paris than in Montréal.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate now = LocalDate.now( zoneId );
LocalDate then = LocalDate.of( 2001, 1, 1 );
Period period = Period.between( then, now );
Then: 2001-01-01. Now: 2015-09-07. Period: P14Y8M6D. Days: 5362
For whole days, then Daylight Saving Time (DST) is irrelevant.
If you want a count of total days, use the ChronoUnit enum which includes some calculation methods. Notice the calculations return a long.
long days = ChronoUnit.DAYS.between( then, now ); // "5362" seen above.
I have asked about doing a full period in java.time, including hours, minutes, seconds. Not possible as of Java 8. A surprising workaround using the bundled libraries was suggested by Meno Hochschild: Use a Duration class found in the javax.xml.datatype package.
Joda-Time
Here is some example code in Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime start = new DateTime( 2014, 1, 2, 3, 4, 5, timeZone );
DateTime stop = new DateTime( 2014, 5, 2, 3, 4, 5, timeZone );
Period period = new Period( start, stop );
Calling toString will get you a string representation in the form defined by the ISO 8601 standard, PnYnMnDTnHnMnS.
With the date4j library:
int numDaysBetween = oneDate.numDaysFrom(anotherDate);
There is simple way to implement it. We can use Calendar.add method with loop.
For example as below,
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date beginDate = dateFormat.parse("2013-11-29");
Date endDate = dateFormat.parse("2013-12-4");
Calendar beginCalendar = Calendar.getInstance();
beginCalendar.setTime(beginDate);
Calendar endCalendar = Calendar.getInstance();
endCalendar.setTime(endDate);
The minus days between beginDate and endDate, and the code as below,
int minusDays = 0;
while (true) {
minusDays++;
// Day increasing by 1
beginCalendar.add(Calendar.DAY_OF_MONTH, 1);
if (dateFormat.format(beginCalendar.getTime()).
equals(dateFormat.format(endCalendar).getTime())) {
break;
}
}
System.out.println("The substractation between two days is " + (minusDays + 1));
Have Fun! #.#
I disagree with the claim that Java doesn't have a mechanism for calculating the difference between dates.
Java was designed for global use. It was designed so that there isn't a concept of date, there is only a concept of "time in milliseconds". Any interpretation of such a universal time as the time-and-date in a specific location under a specific convention is merely a projection or a view.
The calendar class is used to turn this sort of absolute time into dates. You can also add or subtract date components, if you really need to. The only way to provide a difference in term of components between two times would be Calendar generated and specific. Thus, you could argue that the standard library does not include a smart enough Gregorian Calendar, and I would agree that it leaves some to be desired.
That being said, there are numerous implementations of this kind of functionality, I see others have provided examples.
Java's implementation of dates is poor. If you find Joda-Time too complicated, try my little contribution to open source:
http://calendardate.sourceforge.net/javadoc/index.html