C H A P T E R  3

image

Numbers and Dates

Numbers play a significant role in many applications. As such, it is helpful to know how to use them correctly within the context of the work that you are trying to perform. This chapter will help you to understand how to perform some of the most basic operations with numbers, and it will also provide insight on performing advanced tasks such as working with currency. Dates can also become important as they can be used for many different reasons within an application. In this chapter, you will learn how to work with dates and how to perform calculations with them.

This chapter will also cover some new additions to the Java language with the Java 7 release. There have been some minor but important updates to binary literals and numeric literals that will be demonstrated in this chapter. In the end, you will learn how to perform essential tasks with both numbers and dates in order to make your application development easier.

3-1. Rounding Float and Double Values to Integers

Problem

You need to have the ability to round floating-point numbers or doubles within your application to an Integer value.

Solution

Use one of the java.lang.Math round() methods to round the number into the format you require. The Math class has two different methods that can be used for rounding floating-point numbers or Double values. The following code demonstrates how to use each of these methods:

public static int roundFloatToInt(float myFloat){
    return Math.round(myFloat);
}

public static long roundDoubleToLong(double myDouble){
    return Math.round(myDouble);
}

The first method, roundFloatToInt(), accepts a floating-point number and uses the java.lang.Math class to round that number to an Integer. The second method, roundDoubleToLong(), accepts a Double value and uses the java.lang.Math class to round that Double to a Long.

How It Works

The java.lang.Math class contains plenty of helper methods to make our lives easier when working with numbers. The round() methods are no exception as they can be used to easily round floating-point or double values. One version of the java.lang.Math round() method accepts a float as an argument. It will round the float to the closest int value, with ties rounding up. If the argument is NaN, then a zero will be returned. When arguments that are positive or negative infinity are passed into round(), a result equal to the value of Integer.MAX_VALUE or Integer.MIN_VALUE will be returned respectively. The second version of the java.lang.Math round() method accepts a double value. The double value is rounded to the closest long value, with ties rounding up. Just like the other round(), if the argument is Not a Number (NaN), a zero will be returned. Similarly, when arguments that are positive or negative infinity are passed into round(), a result equal to the value of Long.MAX_VALUE or Long.MIN_VALUE will be returned, respectively.

images Note The NaN, POSITIVE_INFINITY, and NEGATIVE_INFINITY values are constant values defined within the Float and Double classes. NaN (Not a Number) is an undefined or unrepresentable value. For example, a NaN value can be produced by dividing 0.0f by 0.0f. The values represented by POSITIVE_INFINITY and NEGATIVE_INFINITY refer to values that are produced by operations that generate such extremely large or negative values of a particular type (floating-point or double) that they cannot be represented normally. For instance, 1.0/0.0 or -1.0/0.0 would produce such a value.

3-2. Formatting Double and Long Decimal Values

Problem

You need to have the ability to format double and long numbers within your application.

Solution

Use the DecimalFormat class to format and round the value to the precision your application requires. In the following method, a double value is accepted and a formatted String value is printed:

public static void formatDouble(double myDouble){
    NumberFormat numberFormatter = new DecimalFormat("##.000");
    String result = numberFormatter.format(myDouble);
    System.out.println(result);
}

For instance, if the double value passed into the formatDouble() method is 345.9372, the following will be the result:

345.937

Similarly, if the value .7697 is passed to the method, the following will be the result:

.770

Each of the results is formatted using the specified pattern and rounded accordingly.

How It Works

The DecimalFormat class can be used along with the NumberFormat class to round and/or format double or long values. NumberFormat is an abstract class that provides the interface for formatting and parsing numbers. This class provides the ability to format and parse numbers for each locale, and obtain formats for currency, percentage, integers, and numbers. By itself, the NumberFormat class can be very useful as it contains factory methods that can be used to obtain formatted numbers. In fact, little work needs to be done in order to obtain a formatted String. For example, the following code demonstrates the calling of some factory methods on NumberFormat class:

// Obtains an instance of NumberFormat class
NumberFormat format = NumberFormat.getInstance();

// Format a double value for the current locale
String result = format.format(83.404);
System.out.println(result);

// Format a double value for an Italian locale
result = format.getInstance(Locale.ITALIAN).format(83.404);
System.out.println(result);

// Parse a String into a Number
try {
    Number num = format.parse("75.736");
    System.out.println(num);
} catch (java.text.ParseException ex){
    System.out.println(ex);
}

To format using a pattern, the DecimalFormat class can be used along with NumberFormat. In the solution to this recipe, you saw that creating a new DecimalFormat instance by passing a pattern to its constructor would return a NumberFormat type. This is because DecimalFormat extends the NumberFormat class. Because the NumberFormat class is abstract, DecimalFormat contains all the functionality that NumberFormat contains, plus added functionality for working with patterns. Therefore, it can be used to work with different formats from the locales just as you have seen in the previous demonstration. This provides the ultimate flexibility when working with double or long formatting.

As mentioned previously, the DecimalFormat class can take a String-based pattern in its constructor. You can also use the applyPattern() method to apply a pattern after the fact. Each pattern contains a prefix, numeric part, and suffix, which allows you to format a particular decimal value to the required precision, and include leading digits and commas as needed. The symbols that can be used to build patterns are displayed in Table 3-1. Each of the patterns also contains a positive and negative subpattern. These two subpatterns are separated by a semicolon (;), and the negative subpattern is optional. If there is no negative subpattern present, the localized minus sign is used. For instance, a complete pattern example would be “###,##0.00;(###,##0.00)".

images

The DecimalFormat class provides enough flexibility to format double and long values for just about every situation.

3-3. Comparing int Values

Problem

You need to compare two or more int values.

Solution #1

Use the comparison operators to compare Integer values against one another. In the following example, three int values are compared against each other, demonstrating various comparison operators:

int int1 = 1;
int int2 = 10;
int int3 = -5;

System.out.println(int1 == int2);  // Result:  false
System.out.println(int3 == int1);  // Result:  false
System.out.println(int1 == int1);  // Result:  true
System.out.println(int1 > int3);    // Result:  true
System.out.println(int2 < int3);    // Result:  false

As you can see, comparison operators will generate a Boolean result.

Solution #2

Use the Integer.compare(int,int) method to compare two int values numerically. The following lines could compare the same int values that were declared in the first solution:

System.out.println("Compare method -> int3 and int1: " + Integer.compare(int3, int1));
// Result -1
System.out.println("Compare method -> int2 and int1: " + Integer.compare(int2, int1));
// Result 1

How It Works

Perhaps the most commonly used numeric comparisons are against two or more int values. The Java language makes it very easy to compare an int using the comparison operators (see Table 3-2).

images

The second solution to this recipe demonstrates the Integer compare() method that was added to the language in Java 7. This static method accepts two int values and compares them, returning a 1 if the first int is greater than the second, a 0 if the two int values are equal, and a -1 if the first int value is less than the second. To use the Integer.compare() method, pass two int values as demonstrated in the following code:

Integer.compare(int3, int1));
Integer.compare(int2, int1));

Just like in your math lessons at school, these comparison operators will determine whether the first Integer is equal to, greater than, or less than the second Integer. Straightforward and easy to use, these comparison operators are most often seen within the context of an if statement.

3-4. Comparing Floating-Point Numbers

Problem

You need to compare two or more floating-point values in an application.

Solution #1

Use the Float object’s compareTo() method to perform a comparison of one Float against another. The following example shows the compareTo() method in action:

Float float1 = new Float("9.675");
Float float2 = new Float("7.3826");
Float float3 = new Float("23467.373");

System.out.println(float1.compareTo(float3));  // Result: -1
System.out.println(float2.compareTo(float3));  // Result: -1
System.out.println(float1.compareTo(float1));  // Result: 0
System.out.println(float3.compareTo(float2));  // Result: 1

The result of calling the compareTo() method is an Integer value. A negative result indicates that the first float is less than the float that it is being compared against. A zero indicates that the two float values are equal. Lastly, a positive result indicates that the first float is greater than the float that it is being compared against.

Solution #2

Use the Float class compare() method to perform the comparison. The following example demonstrates the use of the Float.compare(float, float) method.

System.out.println(Float.compare(float1, float3));
System.out.println(Float.compare(float2, float3));
System.out.println(Float.compare(float1, float1));
System.out.println(Float.compare(float3, float2));

How It Works

The most useful way to compare two Float objects is to make use of the compareTo() method. This method will perform a numeric comparison against the given float objects. The result will be an integer value indicating whether the first Float is numerically greater than, equal to, or less than the Float that it is compared against. If a float value is NaN, it is considered to be equal to other NaN values or greater than all other float values. Also, a float value of 0.0f is greater than a float value of -0.0f.

An alternative to using compareTo() is the compare() method, which is also native to the Float class. The compare() method was introduced in Java 1.4, and it is a static method that compares two float values in the same manner as compareTo(). It only makes the code read a bit differently. The format for the compare() method is as follows:

Float.compare(primitiveFloat1, primitiveFloat2)

The compare() method shown will actually make the following call using compareTo():

new Float(float1).compareTo(new Float(float2)

In the end, the same results will be returned using either compareTo() or compare().

3-5. Performing Calculations with Complex Numbers

Problem

You have a requirement to perform calculations with complex numbers in your Java application.

Solution

Download the Apache Commons Math library and make use of the Complex class. The Commons Math library makes it easy to work with complex numbers. In the following example code, a Java class including import statements for the Apache Commons Math library demonstrates how to create complex numbers and perform arithmetic operations:

import org.apache.commons.math.complex.Complex;

public class ComplexNumberExamples {

    public static void main(String[] args){
        complexArithmetic();
    }

    public static void complexArithmetic(){

        // Create complex numbers by passing two floats to the Complex class
        Complex complex1 = new Complex(8.0, 3.0);
        Complex complex2 = new Complex(4.2, 5.0);
        Complex complex3 = new Complex(8.7, 13.53);
        Complex result;

        // Find the absolute value of a complex number
        double absresult = complex1.abs();

        // Compute the exponential function
        Complex exp = complex1.exp();

        // Add two complex numbers together
        result = complex1.add(complex2);

        // Subtract two complex numbers
        result = complex2.subtract(complex3);

        // Divide two complex numbers
        result = complex2.divide(complex3);

        // Multiply two complex Numbers
        result = complex1.multiply(complex2);

        // Multiply a complex number and a double
        result = complex1.multiply(absresult);

        // Return the additive inverse of a given complex number
        result = complex1.negate();

        // Return the list of the 5th roots for this complex number
        List nth = complex1.nthRoot(5);

        // Computes complex number raised to the power of another
        Complex pow = complex1.pow(complex2);

        // Computes the square root of the complex number
        Complex sqrt = complex1.sqrt();

        // Retrieve the real and imaginary parts of the result
        double real = result.getReal();
        double imag = result.getImaginary();

        // Obtain the tangent
        result = complex1.tan();  
    }
}

This example provides you with a solid foundation on how to use the Apache Commons Math library to work with complex numbers. To learn more about printing out the results of an imaginary number and formatting properly, please see recipe 3-6.

How It Works

Complex numbers consist of two parts: real and imaginary. For the most part, they are used in scientific and engineering fields, and they make it possible to extend the real value of a number so that problems can be solved. The issue with using complex numbers in Java is that there are no classes built into the language for working with them properly. Therefore, many people have worked around this by building their own complex number classes to work with them. As a result, there are hundreds of different Complex.java classes (or some named similarly) that can be found on the Web. In this book, we will use one of the most widely accepted libraries, the Apache Commons Math library, to tackle tasks such as these when possible. This library contains its own set of classes for working with complex numbers. To get started, the first thing you need to do is download the latest JAR files for the Apache Commons Math library from its location on the web (http://commons.apache.org/math/), and place the JAR files in your CLASSPATH. As of this writing, release 2.2 was the most current version. Therefore, the examples in the solution to this recipe might differ if you are using a different version of the library. The Apache Commons Math library will contain at least two JAR files. Version 2.2 contains three JAR files, and these files include the library, sources, and Javadoc. Make sure you place the JAR file that contains the compiled library into your CLASSPATH. This JAR will be named commons-math-2.2.jar, but the version number might differ if you are using another one. If you are using an IDE, you might want to also include the Javadoc JAR file into your CLASSPATH as this will allow the IDE to display the associated Javadoc with a method when you are using auto-completion.

Once the JARs are downloaded and in your CLASSPATH, you need to import the appropriate classes into the class from which you wish to make use of the library. Once imported, you can create complex numbers using the Complex class, perform calculations, and manipulate them as needed. To create a complex number object using the library, pass two double arguments to the constructor. The first double represents the real number part, and the second represents the imaginary part. The following code creates a complex number that includes a real part with a value of 8.0 and an imaginary part with a value of 3.0:

Complex complex1 = new Complex(8.0, 3.0);

After you’ve created a complex number object, you can work with it by calling the various methods contained within it. Most of the methods contained within the Complex class are used to perform mathematical calculations, while a handful of helper methods are used to gain access to different parts of the number, see if the number is NaN, and other miscellaneous tasks. The mathematical methods include those that are useful for performing everyday mathematics, as well as those that are useful for working with the numbers in a trigonometric methodology. A summary of the standard mathematical methods can be seen in Table 3-3.

images

To make use of these methods, you call them against any given complex number object. All the methods that perform a calculation against two complex numbers accept another Complex object as an argument. A demonstration of these methods can be seen in the solution to this recipe.

Trigonometric methods can also be called against a Complex object, and they do not accept any arguments. They each return a Complex object. A summary of the trigonometric Complex class methods can be seen in Table 3-4.

images

You can see some of these trigonometric methods demonstrated in the solution to this recipe. You might have noticed that earlier in this section the NaN symbol was used. This is comparable to a NULL value for a Complex object. The isNaN() method can be called against a Complex object to return a Boolean value stating whether the object is NaN. To test the equality of two Complex objects, simply call the equals() method, as the following code demonstrates: it returns a Boolean value indicating whether the two Complex objects are equal to each other:

complex1.equals(complex2);

There are a few more methods that can be used on a Complex object, and you can see the documentation for more information on them. As you might have noticed, the solution to this recipe does not print out the values for any of the manipulations that were performed. To learn more about formatting and printing complex number values, see recipe 3-6.

3-6. Formatting and Parsing Complex Numbers

Problem

You have a requirement to format complex numbers with your Java application.

Solution

Download the Apache Commons Math library (refer to recipe 3-5 for more details) and make use of the ComplexFormat class. This class will allow you to properly format the complex number and convert it to a String that represents both the real and imaginary number parts. The following code demonstrates the use of the ComplexFormat class:

ComplexFormat format = new ComplexFormat(); // default format
Complex c = new Complex(3.1415, 7.846);
String s = format.format(c);
System.out.println(s); // prints = 3.14 + 7.85i

NumberFormat numformat = NumberFormat.getInstance();
numformat.setMinimumFractionDigits(3);
numformat.setMaximumFractionDigits(3);

ComplexFormat format2 = new ComplexFormat(numformat);
s = format2.format(c);
System.out.println(s); // prints: 3.142 + 7.846i

The ComplexFormat class also allows for the parsing of Strings into Complex objects. The code that follows demonstrates parsing a String into a Complex object:

ComplexFormat cf = new ComplexFormat();
Complex complexNum = null;
try {
    complexNum = cf.parse("1.110 + 2.222i");
} catch (ParseException ex) {
    ex.printStackTrace();
}

In the previous code, the String is parsed using the ComplexFormat class, and a Complex object, complexNum, is generated.

How It Works

The ComplexFormat class extends the java.text.Format class. Much like other classes that extend java.text.Format, new instances of ComplexFormat can be generated and then different attributes can be set on those instances in order to obtain the required formatting for an application. By default, ComplexFormat will generate a String in the standard complex number format, including the real and imaginary number parts separated by a plus (+) symbol. The ComplexFormat class can also be used to take a complex number in String format and parse it into a Complex object. Doing such conversions can often come in quite handy, especially if you are accepting input from a user.

3-7. Calculating Monetary Values

Problem

You are developing an application that requires the use of monetary values and you are not sure which data type to use for storing and calculating currency values.

Solution

Use the BigDecimal data type to perform calculation on all monetary values. Format the resulting calculations using the NumberFormat.getCurrencyInstance() helper method. In the following code, three monetary values are calculated using a handful of the methods that are part of the BigDecimal class. The resulting calculations are then converted into double values and formatted using the NumberFormat class. First, take a look at how these values are calculated:

BigDecimal currencyOne = new BigDecimal("25.65");
BigDecimal currencyTwo = new BigDecimal("187.32");
BigDecimal currencyThree = new BigDecimal("4.86");
BigDecimal result = null;
String printFormat = null;

// Add all three values
result = currencyOne.add(currencyTwo).add(currencyThree);
// Convert to double and send to formatDollars(), returning a String
printFormat = formatDollars(result.doubleValue());
System.out.println(printFormat);

// Subtract the first currency value from the second
result = currencyTwo.subtract(currencyOne);
printFormat = formatDollars(result.doubleValue());
System.out.println(printFormat);

Next, let’s take a look at the formatDollars() method that is used in the code. This method accepts a double value and performs formatting on it using the NumberFormat class based upon the U.S. locale. It then returns a String value representing currency:

public static String formatDollars(double value){
    NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(Locale.US);
    return dollarFormat.format(value);
}

As you can see, the NumberFormat class allows for currency to be formatted per the specified locale. This can be very handy if you are working with an application that deals with currency and has an international scope.

$217.83
$161.67

How It Works

Many people attempt to use different number formats for working with currency. While it might be possible to use any type of numeric object to work with currency, the BigDecimal class was added to the language to help satisfy the requirements of working with currency values, among other things. Perhaps the most useful feature of the BigDecimal class is that it provides complete control over rounding. This is essentially why such a class is so useful for working with currency values. The BigDecimal class provides an easy API for rounding values, and also makes it easy to convert to double values such as the solution to this recipe demonstrates.

images Note The use of BigDecimal for working with monetary values is a good practice. However, it can come at some performance expense. Depending upon the application and performance requirements, it might be worth using Math.round() to achieve basic rounding if performance becomes an issue.

To provide specific rounding with the BigDecimal class, you should use a MathContext object or the RoundingMode enumeration values. In either case, such precision can be omitted by using a currency formatting solution such as the one demonstrated in the solution example. BigDecimal objects have mathematical implementations built into them, so performing such operations is an easy task. The arithmetic operations that can be used are described in Table 3-5.

images

After performing the calculations you require, call the doubleValue() method on the BigInteger object to convert and obtain a double. You can then format the double using the NumberFormat class for currency results.

3-8. Randomly Generating Values

Problem

An application that you are developing requires the use of randomly generated numbers.

Solution #1

Use the java.util.Random class to help generate the random numbers. The Random class was developed for the purpose of generating random numbers for a handful of the Java numeric data types. This code demonstrates the use of Random to generate such numbers:

// Create a new instance of the Random class
Random random = new Random();

// Generates a random Integer
int myInt = random.nextInt();

// Generates a random Double value
double myDouble = random.nextDouble();

// Generates a random float
float myFloat = random.nextFloat();

// Generates a random Gaussian double
// mean 0.0 and standard deviation 1.0
// from this random number generator's sequence.
double gausDouble = random.nextGaussian();

// Generates a random Long
long myLong = random.nextLong();

// Generates a random boolean
boolean myBoolean = random.nextBoolean();

Solution #2

Make use of the Math.random() method. This will produce a double value that is greater than 0.0, but less than 1.0. The following code demonstrates the use of this method:

double rand = Math.random();

How It Works

The java.util.Random class uses a 48-bit seed to generate a series of pseudo-random values. As you can see from the example in the solution to this recipe, the Random class can generate many different types of random number values based upon the given seed. By default, the seed is generated based upon a calculation derived from the number of milliseconds that the machine has been active. However, the seed can be set manually using the Random setSeed() method. It should be noted that if two Random objects have the same seed, they will produce the same results.

It should be noted that there are cases in which the Random class might not be the best choice for generating random values. For instance, if you are attempting to use a threadsafe instance of java.util.Random, you might run into performance issues if working with many threads. In such a case, you might consider using the ThreadLocalRandom class instead. To see more information regarding ThreadLocalRandom, see the documentation at http://download.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadLocalRandom.html. Similarly, if you require the use of a cryptographically secure Random object, consider the use of SecureRandom. Documentation regarding this class can be found at http://download.oracle.com/javase/7/docs/api/java/security/SecureRandom.html.

The java.util.Random class comes in very handy when you need to generate a type-specified random value. Not only is it easy to use but it also provides a wide range of options for return-type. Another easy technique is to use the Math.random() method, which produces a double value that is within the range of 0.0 to 1.0, as demonstrated in solution #2. Both techniques provide a good means of generating random values. However, if you need to generate random numbers of a specific type, java.util.Random is the best choice.

3-9. Obtaining the Current Date

Problem

You are developing an application for which you would like to obtain the current date to display on a form.

Solution #1

If you only need to obtain the current date without going into calendar details, use the java.util.Date class to generate a new Date object. Doing so will cause the new Date object to be equal to the current system date. In the following code, you can see how easy it is to create a new Date object and obtain the current date:

Date date = new Date();

System.out.println(date);
System.out.println(date.getTime());

The result will be a Date object that contains the current date and time taken from the system that the code is run on, as shown following. The time is the number of milliseconds since January 1, 1970, 00:00:00 GMT.

Sat Sep 10 14:45:57 CDT 2011
1315683957625

Solution #2

If you need to be more precise regarding the calendar, use the java.util.Calendar class. Although working with the Calendar class will make your code longer, you can be much more precise. The following code demonstrates just a handful of the capabilities of using this class to obtain the current date:

Calendar gCal = Calendar.getInstance();

// Month is based upon a zero index, January is equal to 0,
// so we need to add one to the month for it to be in
// a standard format
int month = gCal.get(Calendar.MONTH) + 1;int day = gCal.get(Calendar.DATE);
int yr = gCal.get(Calendar.YEAR);

String dateStr = month + "/" + day + "/" + yr;
System.out.println(dateStr);

int dayOfWeek = gCal.get(Calendar.DAY_OF_WEEK);

// Print out the integer value for the day of the week
System.out.println(dayOfWeek);

int hour = gCal.get(Calendar.HOUR);
int min  = gCal.get(Calendar.MINUTE);
int sec = gCal.get(Calendar.SECOND);


// Print out the time
System.out.println(hour + ":" + min + ":" + sec);

// Create new DateFormatSymbols instance to obtain the String
// value for dates
DateFormatSymbols symbols = new DateFormatSymbols();
String[] days = symbols.getWeekdays();
System.out.println(days[dayOfWeek]);

// Get crazy with the date!
int dayOfYear = gCal.get(Calendar.DAY_OF_YEAR);
System.out.println(dayOfYear);

// Print the number of days left in the year
System.out.println("Days left in " + yr + ": " + (365-dayOfYear));

int week = gCal.get(Calendar.WEEK_OF_YEAR);
// Print the week of the year
System.out.println(week);

As demonstrated by this code, it is possible to obtain more detailed information regarding the current date when using the Calendar class. The results of running the code would look like the following:

9/10/2011
7
2:45:57
Saturday
253
Days left in 2011: 112
37

How It Works

Many applications require the use of the current calendar date. It is often also necessary to obtain the current time. There are a couple of different ways to do that, and the solution to this recipe demonstrates two of them. By default, the java.util.Date class can be instantiated with no arguments to return the current date and time. The Date class can also be used to return the current time of day via the getTime() method. As mentioned in the solution, the getTime() method returns the number of milliseconds since January 1, 1970, 00:00:00 GMT, represented by the Date object that is in use. There are several other methods that can be called against a Date object with regards to breaking down the current date and time into more granular intervals. For instance, the Date class has the methods getHours(), getMinutes(), getSeconds(), getMonth(), getDay(), getTimezoneOffset(), and getYear(). However, it is not advisable to use any of these methods, with the exception of getTime(), because each has been deprecated by the use of the java.util.Calendar get() method. When some method or class is deprecated, that means it should no longer be used because it might be removed in some future release of the Java language. However, a few of the methods contained within the Date class have not been tagged as deprecated, so the Date class will most likely be included in future releases of Java. The methods that were left intact include the comparison methods after(), before(), compareTo(), setTime(), and equals(). Solution #1 to this recipe demonstrates how to instantiate a Date object and print out the current date and time.

As mentioned previously, the Date class has many methods that have become deprecated and should no longer be used. In solution #2 of this recipe, the java.util.Calendar class is demonstrated as the successor for obtaining much of this information. The Calendar class was introduced in JDK 1.1, at which time many of the Date methods were deprecated. As you can see from solution #2, the Calendar class contains all the same functionality that is included in the Date class, except the Calendar class is much more flexible. The Calendar class is actually an abstract class that contains methods that are used for converting between a specific time and date, and manipulating the calendar in various ways. The Calendar, as demonstrated in solution #2, is one such class that extends the Calendar class and therefore provides this functionality.

In order to obtain the current date with a Calendar object, you first need to instantiate a new Calendar instance using the Calendar.getInstance() method. Once you have created a new Calendar object, you can extract the different date and time intervals using the get() method and passing one of the Calendar object’s static int values. As seen in solution #2 to this recipe, the current date can be extracted and printed using the following lines of code:

Calendar gCal = Calendar.getInstance();

int month = gCal.get(Calendar.MONTH);
int day = gCal.get(Calendar.DATE);
int yr = gCal.get(Calendar.YEAR);

For some applications, the Date class will work fine. For instance, the Date class can be useful when working with timestamps. However, if the application requires detailed manipulation of dates and times then it is advisable to make use of a Calendar class, which includes all the functionality of the Date class and also adds more features. Both solutions to this recipe are technically sound; choose the one that best suits the need of your application.

3-10. Adding and Subtracting Days, Months, and Years

Problem

You would like to perform date calculations within your application.

Solution

Use the java.util.Calendar class to perform date calculations. This class allows you to obtain the Integer representation for a given month, day, or year of a specified date. These Integer values can be used to perform calculations to obtain the desired result.

public static void calculateDates() {
    Calendar cal = Calendar.getInstance();
    String monthStr = null;
    // Note:  month values range from 0 to 11...so add one to the number

    int month = cal.get(Calendar.MONTH);
    int day = cal.get(Calendar.DATE);
    int yr = cal.get(Calendar.YEAR);

    System.out.println("January = " + Calendar.JANUARY);
    System.out.println("June = " + Calendar.JUNE);

    System.out.println("Current Date: " + formatDate(cal));

    // Add two months to current date
    cal.add(Calendar.MONTH, 2);

    System.out.println("Current Date Plus 2 Months: " + formatDate(cal));

    cal = Calendar.getInstance();

    // Subtract 8 months from current date
    cal.add(Calendar.MONTH, -8);

    System.out.println("Current Date Minus 8 Months: " + formatDate(cal));

    cal = Calendar.getInstance();
    cal.add(Calendar.DATE, -8);
    System.out.println("Current Date Minus 8 Days: " + formatDate(cal));

    // Add 15 hours to current date
    cal = Calendar.getInstance();
    cal.add(Calendar.HOUR, 15);
    System.out.println("Current Date Plus 15 Hours: " + formatDate(cal));
}

/**
 * Date formatting method that accepts a Calendar object and returns
 * a formatted String.
 *
 * @param cal
 * @return
 */
public static String formatDate(Calendar cal) {
    SimpleDateFormat simpleFormatter = new SimpleDateFormat("MMM dd yyyy hh:mm:ss aaa");

    return simpleFormatter.format(cal.getTime());

}

The results of running this code will resemble the following:

January = 0
June = 5
Current Date: Sep 11 2011 08:03:48 AM
Current Date Plus 2 Months: Nov 11 2011 08:03:48 AM
Current Date Minus 8 Months: Jan 11 2011 08:03:48 AM
Current Date Minus 8 Days: Sep 03 2011 08:03:48 AM
Current Date Plus 15 Hours: Sep 11 2011 11:03:48 PM

The Calendar class contains methods that make it easy to perform basic mathematics using date and time values.

How It Works

Performing date calculations can be difficult if they require conversion between dates into time or into other measurements. Such is the case if you use the java.util.Date class to perform calculations. In the early days of Java, a Date object was often converted into hours, minutes, and seconds; and time was used to perform mathematics on a given date. This is no longer the case with the use of the Calendar class. The two basic requirements for date calculations are addition and subtraction. Most often, days, weeks, months, or years need to be added or subtracted from a given date. Via the use of the Calendar add() method, each of these two functionalities can be easily performed. The add() method signature can be displayed as follows:

add(int field, int amount)

In the preceding signature, the first argument is an int value that represents the field type that will be added to the given date. The second argument is another int value that represents the number of the field type to add to the given date. The static int field values that can be passed as the first argument are listed in Table 3-6.

images

As demonstrated in solution #2, any of the fields in Table 3-6 can be used with the Calendar.add() method to perform date arithmetic. When using the add() method, pass a negative value for the argument to perform a subtraction. Working with the Calendar class might take a few minutes of use to become familiar with the syntax, but it is flexible and easy to use.

3-11. Finding the Difference Between Two Dates

Problem

You need to determine how many hours, days, weeks, months, or years have elapsed between two dates.

Solution

Use the java.util.concurrent.TimeUnit enum to perform calculations between given dates. Using this enum, you can obtain the Integer values for days, hours, microseconds, milliseconds, minutes, nanoseconds, and seconds. Doing so will allow you to perform the necessary calculations.

// Obtain two instances of the Calendar class
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();

// Set the date to 01/01/2010:12:00
cal2.set(2010,0,1,12,0);
Date date1 = cal2.getTime();
System.out.println(date1);

long mill = Math.abs(cal1.getTimeInMillis() - date1.getTime());
// Convert to hours
long hours = TimeUnit.MILLISECONDS.toHours(mill);
// Convert to days
Long days = TimeUnit.HOURS.toDays(hours);
String diff = String.format("%d hour(s) %d min(s)", hours,
TimeUnit.MILLISECONDS.toMinutes(mill) - TimeUnit.HOURS.toMinutes(hours));
System.out.println(diff);

diff = String.format("%d days", days);
System.out.println(diff);

// Divide the number of days by seven for the weeks
int weeks = days.intValue()/7;
diff = String.format("%d weeks", weeks);
System.out.println(diff);

The output of this code will be formatted to display Strings of text indicating the differences between the current date and the Date object that is created.

How It Works

As with most programmatic techniques, there is more than one way to perform date calculations with Java. However, one of the most useful techniques is to perform calculations based upon the given date’s time in milliseconds. This provides the most accurate calculation because it works on the time at a very small interval: milliseconds. The current time in milliseconds can be obtained from a Calendar object by calling the getTimeInMillis() method against it. Likewise, a Date object will return its value represented in milliseconds by calling the getTime() method. As you can see from the solution to this recipe, the first math that is performed is the difference between the given dates in milliseconds. Obtaining that value and then taking its absolute value will provide the base that is needed in order to perform the date calculations. In order to obtain the absolute value of a number, use the abs() method that is contained in the java.lang.Math class, shown in the following line of code:

long mill = Math.abs(cal1. getTimeInMillis() - date1.getTime());

The absolute value will be returned in long format. The TimeUnit enum can be used in order to obtain different conversions of the date. It contains a number of static enum constant values that represent different time intervals, similar to those of a Calendar object. Those values are displayed below.

images Note An enum type is a type whose fields consist of a fixed set of constant values. Enum types were welcomed to the Java language in release 1.5.

  • DAYS
  • HOURS
  • MICROSECONDS
  • MILLISECONDS
  • MINUTES
  • NANOSECONDS
  • SECONDS

The values speak for themselves with regard to the conversion interval they represent. By calling conversion methods against these enums, long values representing the duration between two dates can be converted. As you can see in the solution to this recipe, first the time unit is established using the enum and then a conversion call is made against that time unit. Take, for instance, the following conversion. First, the time unit of TimeUnit.MILLISECONDS is established. Second, the toHours() method is called against it, and a long value that is represented by the mill field is passed as an argument:

TimeUnit.MILLISECONDS.toHours(mill)

This code can be translated in English as follows: “The contents of the field mill are represented in milliseconds; convert those contents into hours.” The result of this call will be the conversion of the value within the mill field into hours. By stacking the calls to TimeUnit, more-precise conversions can be made. For instance, the following code converts the contents of the mill field into hours and then into days:

TimeUnit.HOURS.toDays(TimeUnit.MILLISECONDS.toHours(mill))

Again, the English translation can be read as “The contents of the field mill are represented in milliseconds. Convert those contents into hours. Next, convert those hours into days."

TimeUnit can make time interval conversion very precise. Combining the precision of the TimeUnit conversions along with mathematics will allow you to convert the difference of two dates into just about any time interval.

3-12. Formatting Dates for Display

Problem

Dates need to be displayed by your application using a specific format. You would like to define that format once and apply it to all dates that need to be displayed.

Solution

Use the java.util.Calendar class to obtain the date that you require and then format that date using the java.text.SimpleDateFormat class. The following example demonstrates the use of the SimpleDateFormat class:

// Create new calendar
Calendar cal = Calendar.getInstance();

// Create instance of SimpleDateFormat class using pattern
SimpleDateFormat dateFormatter1 = new SimpleDateFormat("MMMMM dd yyyy");
String result = null;

result = dateFormatter1.format(cal.getTime());
System.out.println(result);

dateFormatter1.applyPattern("MM/dd/YY hh:mm:ss");
result = dateFormatter1.format(cal.getTime());
System.out.println(result);

dateFormatter1.applyPattern("hh 'o''clock' a, zzzz");
result = dateFormatter1.format(cal.getTime());
System.out.println(result);

Running this example would yield the following result:

June 22 2011
06/22/11 06:24:41
06 o'clock AM, Central Daylight Time

As you can see from the results, the SimpleDateFormat class makes it easy to convert a date into just about any format.

How It Works

Date formatting is a common concern when it comes to any program. People like to see their dates in a certain format for different situations. The SimpleDateFormat class was created so we don’t have to perform manual translations for a given date.

images Note Different date formats are used within different locales, and the SimpleDateFormat class facilitates locale-specific formatting.

To use the class, an instance must be instantiated either by passing a String-based pattern as an argument to the constructor or passing no argument to the constructor at all. There are actually four constructors for instantiating an instance of SimpleDateFormat:

SimpleDateFormat()
SimpleDateFormat(String pattern)
SimpleDateFormat(String pattern, DateFormatSymbols symbols)
SimpleDateFormat(String pattern, Locale locale)

In the solution to this recipe, the second constructor in the preceding list is used. The String-based pattern provides a template that should be applied to the given date and then a String representing the date in the given pattern style is returned. A pattern consists of a number of different characters strung together. Table 3-7 shows the different characters that can be used within a pattern.

images

images

Any of the pattern characters can be placed together in a String and then passed to the SimpleDateFormat class. If the class is instantiated without passing a pattern, the pattern can be applied later using the class’s applyPattern() method. The applyPattern() method also comes in handy when you want to change the pattern of an instantiated SimpleDateFormat object, as seen in the solution to this recipe. The following excerpts of code demonstrate the application of a pattern:

SimpleDateFormat dateFormatter1 = new SimpleDateFormat("MMMMM dd yyyy");
dateFormatter1.applyPattern("MM/dd/YY hh:mm:ss");

Once a pattern has been applied to a SimpleDateFormat object, a long value representing time can be passed to the SimpleDateFormat object’s format() method. The format() method will return the given date ime formatted using the pattern that was applied. The String-based result can then be used however your application requires.

3-13. Comparing Dates

Problem

You need to determine whether one date is equal to or greater than another date.

Solution

Use the comparative methods that are part of java.util.Calendar to determine which date is greater. In the following example, two Calendar objects are instantiated, and then they are compared with each other:

Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();

// Set the date to 01/01/2010:12:00
cal2.set(2010,0,1,12,0);

System.out.println(formatDate(cal1) + " before " + formatDate(cal2) + "? " + cal1.before(cal2));
System.out.println(cal2.compareTo(cal1));

The result of this code demonstration would be a String that displays a Boolean value indicating whether the first date is prior to the second. The second line returned from this code is an int indicating whether the cal1 Calendar object is before or after the cal2 Calendar object. They would resemble something like the following:

Sep 11 2011 09:01:39 AM before Jan 01 2010 12:00:39 PM? false
-1

How It Works

Date comparison methods are conveniently included as part of the java.util.Calendar class. The comparison methods after() and before() that are contained within the Calendar class accept another Calendar object as an argument and return a Boolean indicating whether the Date passed as an argument comes after or before the Calendar object on which the method is invoked.

The Calendar object also has another method named compareTo() that accepts another Calendar object and returns an int indicating if the Calendar argument is before or after the Calendar object on which the method is invoked. The results of the compareTo() method are shown in Table 3-8.

images

3-14. Writing Readable Numeric Literals

Problem

Some of the numeric literals in your application are rather long and you would like to make it easier to tell how large a number is at a glance.

Solution

Use underscores in place of commas or decimals in larger numbers in order to make them more readable. The following code shows some examples of making your numeric literals more readable by using underscores in place of commas:

int million = 1_000_000;
int billion = 1_000_000_000;
float ten_pct = 1_0f;
double exp = 1_234_56.78_9e2;

How It Works

Sometimes working with large numbers can become cumbersome and difficult to read. Because of the release of Java SE7, underscores can now be used within numeric literals in order to make code a bit easier to read. The underscores can appear anywhere between digits within a numeric literal. This allows for the use of underscores in place of commas or spaces to separate the digits and make them easier to read.

images Note Underscores cannot be placed at the beginning or end of a number, adjacent to a decimal point or floating-point literal, prior to an F or L suffix, or in positions where a string of digits is expected.

3-15. Declaring Binary Literals

Problem

You are working on an application that requires the declaration of binary numbers.

Solution

Make use of binary literals to make your code readable. The following code segment demonstrates the use of binary literals.

int bin1 = 0b1100;
short bin2 = 0B010101;
short bin3 = (short) 0b1001100110011001;
System.out.println(bin1);
System.out.println(bin2);
System.out.println(bin3);

This will result in the following output:

12
21
-26215

How It Works

Binary literals became part of the Java language with the release of JDK 7. The types byte, short, int, and long can be expressed using the binary number system. This feature can help to make binary numbers easier to recognize within code. In order to use the binary format, simply prefix the number with 0b or 0B.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.216.71