Java for C# Programmers 5: Date & Time

Date, Calendar And Joda-Time

Very early developers found out that Java’s Date class is bad and it is not possible to improve it. Because of this, most methods of Java’s Date class are deprecated now and early the class Calendar has been added.

But soon after adding Calendar, people realized that Calendar is not very good as well. Then development of the successor API Joda-Time started.

Joda-Time is available from Java SE 8 on. It is located in the namespace java.time and contains the main classes LocalDate, LocalTime and LocalDateTime. Joda-Time contains full support of timezones with classes ZoneId, ZonedDateTime, OffsetTime, OffsetDateTime and ZoneOffset. The older class java.util.TimeZone is deprecated.

Joda-Time supports periods of time with the classes Period and Duration. Both are similar to C#’s TimeSpan. Period and Duration deal with different precisions.

// 3 years, 2 months, 1 day
Period period = Period.of(3, 2, 1);

// You can modify the values of dates using periods
LocalDate newDate = oldDate.plus(period);

// Components of a Period are represented by ChronoUnit values
assertEquals(1, period.get(ChronoUnit.DAYS)); 

// A duration of 3 seconds and 5 nanoseconds
Duration duration = Duration.ofSeconds(3, 5);

As expected, you can add and subtract durations and you can modify date values with durations.

Joda-Time also contains

  • Chronolgy and associated classes to represent calendars different from the Gregorian calendar.
  • MonthDay to represent a birthday.
  • YearMonth to represent a credit card expiration date.

From Java SE 8 on all three date-time systems (Date, Calendar and Joda-Time) exist in Java in parallel.

Date Formatting

Locale Specific

It is easy to format a Date in a localized way.

DateFormat daf = DateFormat.getDateInstance(DateFormat.SHORT, 
        Locale.German);
Date now = new Date();         // new Date() is now. 
String s = daf.format(now);    // "15.05.14"  for 15th of May 2014

DateFormat tif = DateFormat.getTimeInstance(DateFormat.SHORT, 
        Locale.German);
String z = tif.format(now);    // "09:54"     for 9:54 AM

// uses the current locale
DateFormat.getDateInstance(DateFormat.SHORT); 

// long date and short time combined
DateFormat dtf = DateFormat.getDateTimeInstance(DateFormat.LONG,
        DateFormat.SHORT, Locale.GERMAN);
String a = dtf.format(now);   // "15. Mai 2014 09:54"

These are the available style constants and the resulting output for 15th of May 2014, 09:51:17 o’clock with locale ENGLISH.

Style Date Time
DateFormat.SHORT 5/15/14 9:51 AM
DateFormat.MEDIUM May 15, 2014 9:51:17 AM
DateFormat.LONG May 15, 2014 9:51:17 AM CEST
DateFormat.FULL Thursday, May 15, 2014 9:51:17 AM CEST

Extended Date Formatting

You have full control over your date format with the class SimpleDateFormat and format placeholder strings.

    now = new Date(114, 0, 17, 14, 15, 16);  

    daf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    System.out.println(daf.format(now));        // 2014-01-17 14:15:16

    daf = new SimpleDateFormat("dd. MMM yy HH:mm");
    System.out.println(daf.format(now));        // 17. Jan 14 14:15

Gotcha: The format strings in Java are quite similar to those used in C#, but not identical. Look there for details:
http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html.

Date Oddities

If you are using Java’s Date, be aware of its oddities.

  • getMonth() is zero-based.
  • getDay() returns the day of week, not the day of month.
  • getDate() returns the day of month, 1-based.
  • getYear() returns the gregorian year minus 1900.

If today was Tuesday, 13th of May 2014…

Date d = new Date();
String z = String.format("%04d-%02d-%02d", 
        d.getYear(), d.getMonth(), d.getDay());
System.out.println(z);

Gotcha: this would print 0114-04-02. Not one of the three numbers is what I would have expected before having studied the intricacies of Date.

Stopwatch

There’s nothing like C#’s Stopwatch in plain Java. There are stopwatches available in org.apache.commons.lang.time.StopWatch and one in com.google.common.base.Stopwatch.

If you don’t want to pull in these packages, you can use
System.currentTimeMillis() or System.nanoTime() to imitate a simple stopwatch.

Function Returns
System.currentTimeMillis() Returns the current time in milliseconds. Date d = new Date(System.currentTimeMillis()) will represent the current time.
System.nanoTime() Returns nanoseconds since some fixed but arbitrary origin time which even may vary between different instances of Java VMs. Only use nanoTime() for profiling.

Java for C# Programmers 4: Exceptions & Arrays

Exceptions

Java has exceptions with try/catch/finally. They work roughly the same way as in C#.

  • Gotcha: In C#, the stack trace is put into the exception when the exception is thrown. In Java, the stack trace is calculated, when the exception is created. Re-read the previous sentence, please.
  • Rethrowing an exception in Java works like this:
    catch (Exception e) { throw e; }
    This works in Java only because throwing an exception does not recalculate its stack.
  • The ex.getMessage() may be null, even with standard system exceptions. This is never the case in C#. At least I’ve never seen it there.
  • On the other hand, you can call System.out.println(ex.getMessage()); without problems in Java. It writes null to the screen. In C#, this will throw, if ex.getMessage() is null.
  • Gotcha: In Java return is allowed in a finally block, which is not in C#. This may lead to unexpected behaviour.
  • You can catch multiple types of exceptions in one clause.
    catch ( IOException | SQLException ex ) { ... }

Checked Exceptions

In Java, there are two types of exceptions. Checked and unchecked exceptions. Unchecked exceptions are those which derive from RuntimeException, checked exceptions extend Exception. In C#, there are only unchecked exceptions.

Checked exceptions are an interesting feature.

If a method X can throw one or several checked exceptions, it must announce this in its declaration with the throws keyword like this:
void ReadMyFile(String filename) throws IOException

What follows: if a method M calls a method X which may throw a checked exception Ex,

  • M itself must catch Ex or
  • M itself declares that it may throw Ex via throws Ex

This is enforced by the compiler.
At first glance, it seems that checked exceptions make things easier for library developers and library users… But at second glance, it seems checked exceptions are deprecated in the Java community. Probably the main point of this interesting post about checked exceptions is:

When you choose to use checked exception for errors that you think are recoverable, you try to decide for the client of your API, whereas only he may know what’s recoverable and what isn’t in his own context.

Hejlsberg, the main developer of C#, doesn’t like checked exceptions too much also. In an interview about checked exceptions he stated:

The exception handling should be centralized, and you should just protect yourself as the exceptions propagate out to the handler.

Arrays

There are constant length arrays in Java, which are very similar to those in C#. Access is by index starting at zero.

Gotcha: In Java, the array is not connected in any way to the Iterable interface or the collection types. You cannot pass an array where an Iterable is required.

Exception: you can use an array in a for loop.

int[] h4 = {4, 5, 11, 46};
for(int i: h4)
    System.out.printf(" %d", i);  // 4 5 11 46

Creating an Array

Some examples of how to create an array in Java are:

Abc[] a = new Abc[6]; 
  // All members of a are initialized to null, as 
  // Abc is a reference type.

int b[] = new int[4]; 
for(int i = 0; i < a.length; ++i)
    System.out.print(a[i] + " ");   // 0 0 0 0 

b[6] = 67;   // ArrayIndexOutOfBoundsException: 6   

int[] c = new int[] {4, 5, 11};
int[] d = {4, 5, 11, 46};

String[] e = {"a", "b"};

int[] g = new int[5];

Copying an Array or a Part

There are at least three different system methods to copy an array. I am not really sure what are the differences. Probably there are none or none worth to mention.

int[] d = {4, 5, 11, 46};
int[] g = new int[5];
int[] f = d.clone();    // copies d completely

// Copies 3 elements starting at f[0] to g, 
// starting at g[1].
System.arraycopy(f, 0, g, 1, 3);
System.out.println(Arrays.toString(g)); // [0, 4, 5, 11, 0]

int[] h = Arrays.copyOf(d, 3);
System.out.println(h);                  // [I@1b778d0c      
System.out.println(Arrays.toString(h)); // [4, 5, 6]

Class Arrays

The static system class Arrays contains some functions - even some parallel ones - that are helpful when dealing with arrays. The functions are overloaded for all the primitive types and for Object.

Function Purpose
asList creates a List from an array
binarySearch searches an item
copyOf copies, truncating or padding
copyOfRange copies a part
deepEquals checks if 2 arrays are deeply equal
deepToString returns a deep string representation
fill fills an array or a part of an array
parallelPrefix cumulates in parallel all elements
parallelSetAll fills in parallel with generated values
parallelSort sorts an array using a parallel algorithm
setAll fills with generated values
sort sorts completely or sort a range
stream creates a Stream from array
spliterator creates a Spliterator from array

Multi-Dimensional Arrays

An array of arrays (jagged array) is possible and the only type in Java. Real multi-dimensional arrays like in C, C++ and C# do not exist in Java.

int[][] h21 = new int[2][4]; 
int[][][] h3 = new int[2][5][4];

System.out.println(h3.length);          // 2 
System.out.println(h3[0].length);       // 5 
System.out.println(h3[0][0].length);    // 4 

You should always remember that jagged arrays are just arrays of arrays (of arrays, ...) and the length of the second (third, ...) level arrays may be different for every entry.

int[][] h22 = { {11, 12, 13, 14}, {5} };

System.out.println(h22[0].length);      // 4 
System.out.println(h22[1].length);      // 1 

System.out.println(h22[0][3]); // 14 
System.out.println(h22[1][3]); // throws ArrayIndexOutOfBoundsException

It seems the best way to find out the number of dimensions of a multi-dimensional array is to go via the class name.

int[][][][] a = {{{{1},{71}}}};

String className = a.getClass().getName();
System.out.println(className);              // [[[[I
int numberOfDimensions = className.lastIndexOf('[') + 1;
System.out.println(numberOfDimensions);     // 4

Java for C# Programmers 3: Operators & Flow Control

Operators

Mathematical Operators

Increment and decrement operators ++, -- work as in C#, including pre- and postfix notation.

The mathematical operators +, -, , /, %, +=, -=, =, /=, %= and the bitwise operators ~, &, |, ^, <<, >>, &=, |=, ^=, <<=, >>= work as expected.

In Java, there are two additional bitwise operators: >>> and >>>=.
>>> moves the bits to the right and fills all up with zeroes. In contrast, the >> operator fills all up with the sign bit.

// Java
int a = -128;
System.out.println(a >> 1);     // -64
System.out.println(a >>> 1);    // 2147483584

System.out.println(a >> 4);     // -8
System.out.println(a >>> 4);    // 268435448

a = -1;
System.out.println(a >> 1);     // -1
System.out.println(a >>> 1);    // 2147483647

a = 4;
System.out.println(a >> 1);     // 2
System.out.println(a >>> 1);    // 2

The effect of >>> is reachable in C# by using unsigned integers. Or put differently: The >>> is needed in Java because it doesn’t have unsigned integers.

// C#
int a = -128;
uint b = unchecked((uint) -128);
Console.WriteLine(a >> 1);  // -64
Console.WriteLine(b >> 1);  // 2147483584

Console.WriteLine(a >> 4);  // -8
Console.WriteLine(b >> 4);  // 268435448

a = -1;
b = unchecked((uint) -1);
Console.WriteLine(a >> 1);  // -1
Console.WriteLine(b >> 1);  // 2147483647

a = 4;
b = 4;
Console.WriteLine(a >> 1);  // 2
Console.WriteLine(b >> 1);  // 2

Logical Operators

The comparison operators >, >=, ==, <, <=, != are all the same.

Gotcha: In Java, string comparison with == does not compare the contents of the string. In C# it does.

String a = "abc";
String b = "ab";
b += "c";
if (a == b)     // false in Java, true in C#

The logical operators &&, ||, ^, ! work as expected.
In Java like in C# there are also available the boolean operators & and | which do not do short-circuit evaluation.

System.out.println(true | f());  // f will be calculated.  

Flow Control

If, Else And Switch

If, else, switch/case, ?:-operator are the same in Java as in C#, with these differences:

  • switch/case allows fallthrough in Java generally. In C#, fallthrough is allowed only when the label where fallthrough happens does not contain any code.
  • You can't switch on long variables in Java.
  • switch/case allows strings in C#, in Java strings in switch/case are allowed only from Java 7 on.

Gotcha: Java treats the null-String in a switch/case in two completely different ways from C#.

string s = null;
switch(s)
{
    case null: Console.WriteLine("null"); break; 
    default: Console.WriteLine("default"); break;
}

The C# code above will print null. Without the case null part, it will print default.

In Java, the corresponding code including the case null statement will result in a case expressions must be constant expressions compiler error.

Without the case null statement, the code will compile. But at runtime, you'll get a NullPointerException at the switch(s).

Loops And Goto

for, while, do while are all the same. Goto is not available in Java.

The foreach keyword does not exist in Java. Iterating over all of a collection is implemented with a special syntax in for.

// C#
foreach(Type k in array)
// Java
for(Type k: array) 

Java has break and continue with label, these features do not exist in C#.

Break With Label

OuterLoop: // Labels the following loop with 'OuterLoop'
for(int i = 0; i < 3; ++i)
{ 
    for(int j = 0; j < 5; ++j)
    {
        System.out.println("i: " + i + "   j: " + j);
        if(j == 1) 
            break OuterLoop;  // Breaks out of the scope with the 
                       // label OuterLoop. Or put differently: 
                       // jumps behind the end of the statement 
                       // labeled OuterLoop. 
    }
}

The output of the code above is

i: 0  j: 0

Continue With Label

AAA: // Labels the following loop with 'AAA'
for (int i = 0; i < 3; ++i) 
{
    for (int j = 0; j < 5; ++j)
    {
        System.out.println("i: " + i + "   j: " + j);
        if (j == 0)
            continue AAA; // Breaks all inner loops and 
                          // continues the loop labeled AAA.
    }
}

The output of the code above is

i: 0   j: 0
i: 1   j: 0
i: 2   j: 0