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.
You need to have the ability to round floating-point numbers or doubles
within your application to an Integer
value.
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
.
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.
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.
You need to have the ability to format double
and long
numbers within your application.
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.
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)".
The DecimalFormat
class provides enough flexibility to format double
and long
values for just about every situation.
You need to compare two or more int
values.
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.
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
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).
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.
You need to compare two or more floating-point
values in an application.
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.
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));
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()
.
You have a requirement to perform calculations with complex numbers in your Java application.
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.
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.
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.
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.
You have a requirement to format complex numbers with your Java application.
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.
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.
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.
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
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.
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.
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.
An application that you are developing requires the use of randomly generated numbers.
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();
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();
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.
You are developing an application for which you would like to obtain the current date to display on a form.
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
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
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.
You would like to perform date calculations within your application.
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.
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.
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.
You need to determine how many hours, days, weeks, months, or years have elapsed between two dates.
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.
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.
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.
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.
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.
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.
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.
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.
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.
You need to determine whether one date is equal to or greater than another date.
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
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.
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.
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;
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.
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.
You are working on an application that requires the declaration of binary numbers.
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
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
.
3.22.216.71