A guide to Java SimpleDateFormat in examples

Today I want to show you some examples of how you can use SimpleDateFormat class in your code. I hope some of them will be new and surprising!

The basic example

First the most basic usage of the class. Lets use it to format Date object into a simple string showing day, month and a year:

1:
2:
3:
4:
5:
6:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd/MM/yy");
String dateAsString = simpleDateFormat.format(new Date());

System.out.println(dateAsString);
// Result: "12/11/09"

Slightly more advanced

Obviously we can use more complicated patterns than that (see SimpleDateFormat JavaDoc for the full list). Besides adding more data to be shown we can also add some regular text – to do that in a pattern you need to escape the text with an apostrophe. So here is a fancy way of printing the time and date:

1:
2:
3:
4:
5:
6:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("hh:mm 'o''clock on' MMMM dd yyyy");
String dateAsString = simpleDateFormat.format(new Date());

System.out.println(dateAsString);
// Result: "06:49 o'clock on November 12 2009"

Now with Locale

SimpleDateFormat is Locale dependent, so by providing one you can get the Date string localized for specific language or country. This is a date in French:

1:
2:
3:
4:
5:
6:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd MMMM yyyy zzzz G", Locale.FRENCH);
String dateAsString = simpleDateFormat.format(new Date());

System.out.println(dateAsString);
// Result: "12 novembre 2009 Heure du méridien de Greenwich ap. J.-C."

Parse String to Date

Good thing about the SimpleDateFormat class is that it can be used not only for formatting, but also for parsing string into a Date object. In this example the used pattern is exactly the same as used by Date.toString() method. With it we can parse the strings created by Data.toString() back into dates:

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
// SimpleDateFormat that works exactly like Date.toString()
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("E MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
Date today = new Date();

String dateAsString_format = simpleDateFormat.format(today);
String dateAsString_native = today.toString();
// Both strings are: "Thu Nov 12 18:49:36 GMT 2009"

Date parsedDate = simpleDateFormat.parse(dateAsString_native);
System.out.println(parsedDate.toString());
// Result: "Thu Nov 12 18:49:36 GMT 2009"

Setting the default time zone

Notice that when you parse a string into a Date the result may be ambiguous. For example the string “11:23 1 Jan 2001″ is a different moment in time depending whether you live in Japan or Canada. By default Java resolves this by using your local time zone obtained from the default Locale.

Since the time zone may not be a part of the parsed string you may want to set it manually instead using the default one. You can do this with setTimeZone() method:

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);
Date date = simpleDateFormat.parse("13-07-1999");
System.out.println(date);
// Result: "Tue Jul 13 00:00:00 GMT 1999"

simpleDateFormat.setTimeZone(TimeZone.getTimeZone("PST"));
date = simpleDateFormat.parse("13-07-1999");
System.out.println(date);
// Result: "Tue Jul 13 08:00:00 GMT 1999"

Setting the century

Similar ambiguity occurs when parsing two-digit year dates. Whether “01/01/59″ is the new year’s day of 1959 or 2059 can be set by specifying the century to the SimpleDateFormat object. To be specific with set2DigitYearStart() method you can specify the 100 year period in which the parsed date will be placed. By default the 100 year period is [today - 80 years, today + 20 years]. See the example:

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd MMMM yy", Locale.ENGLISH);
Date date = simpleDateFormat.parse("1 November 45");
System.out.println(date);
// By default the year 45 will be taken from period 1929 - 2029
// Result: "Thu Nov 01 00:00:00 GMT 1945"

Date startOf19thCentury = new GregorianCalendar(1801,1,1).getTime();
Date startOf21stCentury = new GregorianCalendar(2001,1,1).getTime();

simpleDateFormat.set2DigitYearStart(startOf19thCentury);
date = simpleDateFormat.parse("1 November 45");
System.out.println(date);
// After invoking set2DigitYearStart() the period is now 1801 - 1901
// Result: "Thu Nov 01 00:00:00 GMT 1845"

simpleDateFormat.set2DigitYearStart(startOf21stCentury);
date = simpleDateFormat.parse("1 November 45");
System.out.println(date);
// This time the period is 2001 - 2101
// Result: "Thu Nov 01 00:00:00 GMT 2045"

Make the parsing more strict

By default the parse method of SimpleDateFormat is very forgiving. If the provided string is not entirely compatible with the pattern, SimpleDateFormat instead of giving up tries with many tricky heuristics to guess what would be the correct answer. In many situations this behavior is more than welcome, but if you do not like this you can disable it. With setLenient() method you can make the parsing obey exactly the pattern and throw an exception if string is invalid.

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd MMMM yyyy", Locale.ENGLISH);
Date date = simpleDateFormat.parse("31 April 1999");
System.out.println(date);
// Since April has only 30 days the parser will assume
// user meant April 30th + one day = May 1st
// Result: "Sat May 01 00:00:00 GMT 1999"

// Make the parsing more strict
simpleDateFormat.setLenient(false);
// This throws java.text.ParseException: Unparseable date: "31 April 1999"
date = simpleDateFormat.parse("31 April 1999");

Using Java SecurityManager to grant/deny access to system functions

In Java it is possible to restrict access to specific functions like reading/writing files and system properties, thread control, networking, object serialization and much more for the running application. Such restrictions may be crucial for guaranteeing security of the system and are implemented for example in Applets, Java Web Start or Java EE Servers.

Class witch takes care of all that security is SecurityManager whose currently registered instance can be accessed through System.getSecurityManager() method. Normally for stand-alone Java applications there is no SecurityManager registered, which means a call to getSecurityManager() would return null. In such case, all the system functions are allowed.

We will show here a simple example of how security in Java works. Take a look at the class below:

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class SecurityTest {
    public static void main(String[] args)
        throws FileNotFoundException {
        //Is there a SecurityManger registered?
        System.out.println("SecurityManager: " +
            System.getSecurityManager());

        //Checking if we can open a file for reading
        FileInputStream fis = new FileInputStream("test.txt");
        System.out.println("File successfully opened");

        //Checking if we can access a vm property
        System.out.println(System.getProperty("file.encoding"));
    }
}

The class first gets the SecurityManager’s instance and prints it out. Note that this step has no influence on two proceeding steps. It’s purpose is just to show clearly if SecurityManager is there or not. Next step is opening a file called ‘test.txt’ for reading. For this step you should create a file ‘text.txt’ (it may be empty) and put it in the application’s directory. Last step reads a system property “file.encoding” which on most systems should be set by default to “UTF-8″.

Now run the program! If you got any exceptions, check if you copied everything well and if you created the file ‘text.txt’ in the program’s directory. If everything went right, you should get the following output:

SecurityManager: null
File successfully opened
UTF-8

First note that the instance of SecurityManager we got from System.getSecurityManager() is null. There is no SecurityManager so everything is allowed and we were able to successfully open a file and read the system property.

Now let’s put security to play! We will need a file defining current security policy. It is a file that tells the SecurityManager what it should allow and what it should deny. Below is an example of such a file:

grant {
};

As you see, there is nothing written inside the ‘grant’ block. It means that there are no permissions specified and (almost) all system functions will be denied. Put that in a file called ‘test.policy’ and place it in the application’s directory (along with file ‘text.txt’). You can read much more about structure of .policy files here.

With the policy file in place, we should tell the JVM to create a SecurityManager and use file ‘test.policy’ for the security policy. We do it by specifying two system properties while running the SecurityTest program: -Djava.security.manager and -Djava.security.policy=test.policy. You can specify them for example in Eclipse in ‘Run Configurations…->Arguments->VM arguments:’ dialog. Alternatively you can specify them straight from the command line (supposing you exported your code to SecurityTest.jar and put it in the same directory where ‘test.policy’ is:

java -Djava.security.manager -Djava.security.policy=test.policy
 -jar SecurityTest.jar

Using these parameters run the program! If everything goes well, this time SecurityManager activates and you should see something like this:

SecurityManager: java.lang.SecurityManager@1a46e30
Exception in thread "main"
    java.security.AccessControlException: access denied
    (java.io.FilePermission test.txt read)
    ...

First line indicates that SecurityManager is registered. The exception you see on the next line is proper behavior. InputFileReader’s constructor internally checks if there is a SecurityManager installed. If so, it calls it to check if reading the specified file is allowed according to the current security policy. The security policy (which we specified in ‘test.policy’ file) contains no permissions for reading a file, so SecurityManager throws AccessControlException.

What to do to allow reading files? We have to put a specific rule to ‘test.policy’. Rules for accessing files are implemented by FilePermission class. You can specify which file the rule applies to and what kind of access is being granted. Below you see what must be written in ‘test.policy’ file:

grant {
  permission java.io.FilePermission "test.txt", "read";
};

This rule grants reading on file ‘text.txt’ (you could also use “<<ALL FILES>>” to grant the reading of all files). With this permission in place, let’s run the program once again:

SecurityManager: java.lang.SecurityManager@1a46e30
File successfully opened
Exception in thread "main"
    java.security.AccessControlException:
    access denied (java.util.PropertyPermission file.encoding read)

As you see this time file was successfully opened, but next exception appeared while trying to read the property “file.encoding”. Permission allowing programs to access system properties is called PropertyPermission. We define it following way:

grant {
  permission java.io.FilePermission "test.txt", "read";
  permission java.util.PropertyPermission "file.encoding", "read";
};

It will allow reading of property “file.encoding”. This time when we run the program, everything will be allowed by the SecurityManager and we should get following output:

SecurityManager: java.lang.SecurityManager@1a46e30
File successfully opened
UTF-8

Writing .policy files for a big application can be tedious, especially if you don’t know yet the correct syntax. Fortunately there is help in form of ‘policytool’, which is a small program distributed along with JDK. You can read something about it here.

This short introduction shows just a tiny bit of SecurityManager’s features. You can do a lot more with it, like for example defining your own permissions and using them in your classes. You can also set principals for every permission and specify files containing digital signatures for them, so that a user running your program must be in possession of a key file to access specific functions. You can read about this functionality for example on this Sun’s tutorial. There is also a bunch of useful links concering security on this site.

How to check if String is parseable to Integer or Double?

This seems basic, right? In most cases it is, but as almost everything in Java this problem has its subtle pitfalls and problems. It is mainly because Java does not provide a simple utility method that can answer this question. Today I wanted to share with you several ways of solving this problem and describe their good and bad sides.

Why should you care?

Checking for that in many cases is unnecessary. If the format of data is defined and its contract states that the string is an integer you can just parse it and deal with unlikely exception that an error occurs. The problem is when there is no such a contract and you have to decide based on whether the string is an integer what actions to perform next. In that case plain try-catch check may be too expensive for you:

1:
2:
3:
4:
5:
6:
7:
8:
public boolean isInteger(String string) {
    try {
        Integer.valueOf(string);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

This method’s execution cost is high because of two factors: one is that to determine if string is an integer we have to do the whole parsing and throw away the result. Second is that we use exception throwing (which is expensive) to direct the program flow. The good thing about this code is its simplicity – you can at a glance say the method is correct.

Let’s use RegExp!

Much faster is to create a regular expression and use it to check whether string contains an integer or double. The good thing about this approach is that the regexp can be precompiled and used several times after:

1:
2:
3:
4:
5:
private static Pattern doublePattern = Pattern.compile("-?\\d+(\\.\\d*)?");

public boolean isDouble(String string) {
    return doublePattern.matcher(string).matches();
}

Unfortunately this method has important flaws: the pattern above will work for the most basic string representation of Double, but what about more advanced like “1.23E-12″. Even if you improve this pattern (belive me, its difficult) there are still some checks that it will not be able to perform, for instance checking if the integer is above Integer.MAX_INT.

What about Scanner?

There is a way of combining the two approaches shown above together: first check with regexp if string is possibly be an integer and if it seems to be one, try to perform the actual parsing. If the regexp is ‘good enough’ the number of false positives resulting in NumberFormatException will be acceptable. The good news is this approach is already implemented by a Scanner class. See the following example:

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
public static void main(String[] args) {
    Scanner scanner = new Scanner("Test string: 12.3 dog 12345 cat 1.2E-3");

    while (scanner.hasNext()) {
        if (scanner.hasNextDouble()) {
            Double doubleValue = scanner.nextDouble();
        } else {
            String stringValue = scanner.next();
        }
    }
}

In essence Scanner breaks down the given string into tokens around whitespace and allows you to iterate trough them. It gives you useful access methods like ‘hasNextDouble()’ to check whether the next token is a Double or not and allows you to get it in a parsed version as a Double with ‘nextDouble()’ method.

Internals of Scanner show that it in fact combines both the regexp and exception catching methods, which makes it quite efficient. The downside is that the Scanner object itself is heavy and prepared to parsing larger text strings, so it may be ineffective if you need to use it on a simple strings like “123″.

Wait! It does not work for me!!

It is possible that you start using one of the methods above on a real life data and at some point things stop making sense… Why? Because we forgot about something important: the numbers are locale-sensitive and its string representation depends from country to country. For instance ten thousand in US is 10,000, in Poland 10 000 and in Italy 10.000. See that none of the methods above could successfully parse neither Polish or Italian numbers! What can you do in those cases? You have to use for parsing a NumberFormat class with specified locale:

1:
2:
3:
4:
5:
6:
private static NumberFormat italianDouble =
        NumberFormat.getNumberInstance(Locale.ITALIAN);

public boolean isItalianDouble(String string) {
    return (italianDouble.parse(string) != null);
}

Now you can finally see that 10,000 is a valid integer. Unfortunately with NumberFormat you get another set of problems – it is too liberal in parsing numbers! The method above will return true for 10,000 and false for both abc and x1, but it will return true also for 10abc as it looks only for a suffix in the string, not a total match.

Conclusion

As you can see none of the solutions shown above is perfect – each of the method aboves has its flaws and advantages. Because of that the choice which one is the best for you strongly depends on the context of your program. The important factors are: how often do you need to do a check like that, what is the false result ratio, whether you parse long human readable text or just few given values and whether you care about locale specific issues. It is also possible that in your code you’ll need a combination of them or to add some specific tweaks to one of them.