Simple Date Processing in Java with LocalDate

Calendar icon
Image courtesy of https://www.stockio.com/free-icon/karlton-icon-set-calendar

I’m working on a project in Java, and I wanted to do some simple processing of dates.  I tried reading the Java tutorials and looking at questions and answers on Stack Overflow, but the solutions they offered were too complicated for what I was looking for, or were using classes that were old and not recommended to be used.  I finally figured out a nice easy way to handle the processing, so I thought I’d document it here.

What I was trying to do

The dates I have are stored in Strings, in the format “YYYY-MM-DD”; for example, June 30, 2019 is stored as “2019-06-30”.  This is a nice easy format to work with; I don’t need to concern myself with timezones or anything complicated, and it’s easy to sort and compare, because I can just do String comparisons with the compareTo() method.

Besides comparisons and sorting, I also want to do some other processing: getting the date the day before, the week before, and the week after.  This isn’t so easy to do; I would need to write a bunch of code that knows how many days there are in the month, and handle the case of moving to previous months or years, and deal with leap years, etc., etc., etc.  Yeah, I know it’s not that hard, but it would be easier to use some pre-existing, exhaustively tested code to do it!

Java’s LocalDate class is the solution

It turns out the best way to do this is to use Java’s LocalDate class, in the java.time package.  A LocalDate object contains a date without a timezone, using the standard Gregorian calendar that we all know and love in Canada (and most of the world).  If you really want to know more details about the calendar (you don’t need to to understand this blog post), you can read about the ISO 8601 calendar on Wikipedia.

Creating a LocalDate object

Creating a LocalDate object was really easy for me.  Because I’ve already got the date stored in my program in a String in the format YYYY-MM-DD, I can just call the parse() method; I pass in the String, and it returns a LocalDate object:

LocalDate someDate = LocalDate.parse( "2019-06-30" );

There are other lots of other methods you can use to create LocalDate objects, but this was all I needed to do.  Take a look at the API for other possible methods, like now() or of().

Converting back to a String

LocalDate provides a toString() method, which returns a String in the YYYY-MM-DD format:

String dateAsString = someDate.toString();

Of course, because Java will call toString() automatically when converting an object to a String, I can display the date with:

System.out.println( "The date is " + someDate );

LocalDate manipulation

If I want to get the day before the current date, I can use the minusDays() method:

LocalDate dayBefore = someDate.minusDays( 1 );

Note that LocalDate objects are immutable; once they’re set, you can’t change them, so the minusDays() method doesn’t change the original date, it returns a new LocalDate object with the new date.  As a result, if I wanted to change the someDate variable, I’d have to do:

someDate = someDate.minusDays( 1 );

If I want to change by other units, there’s also minusWeeks(), minusMonths(), and minusYears().  You can also use the minus() methods for more complicated manipulation, but I didn’t need to bother with that.  So anyways, here’s how I can get the date from the week before:

LocalDate weekBefore = someDate.minusWeeks( 1 );

Similarly, if I want to get the next day, I can use the plusDays() method:

LocalDate dayAfter = someDate.plusDays( 1 );

There are similar methods for plusWeeks(), plusMonths(), plusYears(), and plus().

Comparing LocalDates

LocalDate provides the standard comparison functions that we’re all used to: the equals() method checks if two dates are equal:

someDate.equals( dayBefore )

evaluates to false, and the compareTo() method compares two dates, returning an integer less than, equal to, or greater than zero:

someDate.compareTo( dayBefore )

evaluates to a value greater than 0.

For some reason, my brain has never been able to remember the order of compareTo(); does it compare the parameter to the object, or the object to the parameter?  I always have to try it out in test code, and I inevitably get it the wrong way! But, with LocalDates, there’s some nice comparison methods I can use so I don’t have to think about it!  If I want to see if a date is before, I can use the isBefore() method:

someDate.isBefore( dayBefore )

evaluates to false.  I can wrap my head around that: I just read the code and it makes sense — “is someDate before dayBefore?”

There’s also an isAfter() method:

someDate.isAfter( dayBefore )

evaluates to true.

There’s also an isEqual() method; you can use that, or equals().

I wish there was an isOnOrAfter() or isOnOrBefore() method, but there’s not; I just have to use compareTo() for that.

Other methods

LocalDate provides lots and lots of other methods, but I didn’t need to use them.  Take a look; if you’re wanting to do some simple date manipulation, there might be something there you want to use!

All the code

Here’s the program I used to test all the code in this post:

import java.time.LocalDate;

public class SimpleDateExample {
    public static void main( String[] args ) {
        LocalDate someDate = LocalDate.parse( "2019-06-30" );
        String dateAsString = someDate.toString();
        System.out.println( "dateAsString = " + dateAsString );
        System.out.println( "The date is " + someDate );

        LocalDate dayBefore = someDate.minusDays( 1 );
        System.out.println( "Day before: " + dayBefore );

        // someDate = someDate.minusDays( 1 );
        // System.out.println( "The date is " + someDate );

        LocalDate weekBefore = someDate.minusWeeks( 1 );
        System.out.println( "Week before: " + weekBefore );

        LocalDate dayAfter = someDate.plusDays( 1 );
        System.out.println( "Day after: " + dayAfter );

        System.out.println( "Using equals: " +
            someDate.equals( dayBefore ) );

        System.out.println( "Using compareTo with dayBefore: " +
            someDate.compareTo( dayBefore ) );

        System.out.println( "Using compareTo with dayAfter: " +
            someDate.compareTo( dayAfter ) );

        System.out.println( "Using isBefore: " +
            someDate.isBefore( dayBefore ) );

        System.out.println( "Using isAfter: " +
            someDate.isAfter( dayBefore ) );
    }
}

Blogging 101: Who I Am and Why I’m Here

siteiconIt’s been a long time since I’ve added anything to my blog — almost three years, now that I look back at my last post.  I’ve been meaning to add more entries to my blog, but I just haven’t gotten around to it.  I think the main problem is because I really don’t know what the focus of my blog is, or what I want to blog about.  So, to help me get over this hurdle, I decided to sign up for WordPress’ Blogging 101 course.

The first assignment in this course is to “Introduce Yourself to the World”.  The intention is to blog about who we are and why we’re here.  Maybe if I do this, it will help me to gain a little clarity on why I’m keeping a blog.

Well, here goes…

My name is Shane McDonald.  I live in Saskatoon, Saskatchewan, Canada.  I work as an instructor at Saskatchewan Polytechnic, in the Computer Systems Technology program.  I mostly teach computer programming courses, with a smattering of Word / Excel / PowerPoint / etc. introductory classes thrown in the mix.  Tomorrow is the first day of a new semester; I’ll be teaching a class in Java, and a class in C.

Why am I blogging?  Well, thinking back to when I started this blog, I had a number of reasons:

  • I wanted to get some experience with WordPress.
  • I wanted to practice writing, in order to help to express my thoughts more clearly.
  • I wanted a place to record solutions to computer problems that I’ve run across, and I thought other people might also run across.  I know a quick Google search often helps me to find the solution to problems, but if nobody had bothered to record their solution, it wouldn’t help me out very much.

Thinking about it now, I think that third reason is probably the reason that seems most important to me.  I know I get a good feeling when I see people accessing my posts, and I hope that others are able to solve the same problems I had, but without a lot of searching!  My top post seems to be this one about how to use numbers in formulas in Microsoft Word mail merges; my least popular posts seem to be my series of tips on using the Vi text editor, which was an outgrowth of a set of tips that I had created on a corporate Wiki at a previous employer.

My problem seems to be that I either don’t run across too many problems (yeah, I wish), or that I don’t bother to take the time to record my solutions for posterity (more likely!).

Anyways, by taking this blogging course, I’m hoping to gain a little more focus on my blog, and to get some motivation to write posts.  Who knows, I might even completely change the focus of my blog!  If nothing else, at least I’ve created this one post, and people will see that I still exist!  I’m excited to work through this course and see how things come along!!!