Wednesday, November 11, 2015

Chapter-8 Numbers and Dates

Chapter 8
Numbers and Dates
In Java numbers are represented by the primitives byteshortintlongfloatdouble, and their wrapper classes, which were explained in Chapter 5, “Core Classes.” Dates can be represented by different classes, most commonly by the java.util.Date class. There are three issues when working with numbers and dates: parsing, formatting, and manipulation.
Parsing deals with the conversion of a string into a number or a date. Parsing is commonplace because Java programs often require user input and user input is received as a String. If a program expects a number or a date but receives a String, then the String has to be converted into a number or a date. Conversion is not always straightforward. Before conversion can take place, you first need to read the String and check if it contains characters that make up a number or a date. For example, “123data” is not a number even though it starts with a number. “123.45” is a float, but not an integer. “12/25/2011” looks like a date, but this is only valid if the program is expecting a date in mm/dd/yyyy format. Converting a string to a number is called number parsing, and converting a string to a date is referred to as date parsing.
Once you have a number or a date, you may want to display it in a specific format. For instance, 1000000 may be displayed as 1,000,000 and 12/25/2011 as Dec 25, 2011. This is number formatting and date formatting, respectively.
This chapter discusses number and date parsing, as well as number and date formatting. These tasks are easily achieved in Java as it provides classes for this purpose. In addition, thejava.lang.Math class, which provides methods to perform mathematical operations, is also discussed. On top of that, there is a section on the java.util.Calendar class, a utility for manipulating dates.
Number Parsing
A Java program may require that the user input a number that will be processed or become an argument of a method. For example, a currency converter program would need the user to type in a value to be converted. You can use the java.util.Scanner class to receive user input. However, the input will be a String, even though it represents a number. Before you can work with the number, you need to parse the string. The outcome of a successful parsing is a number.
Therefore, the purpose of number parsing is to convert a string into a numeric primitive type. If parsing fails, for example because the string is not a number or a number outside the specified range, your program can throw an exception.
The wrappers of primitives—the ByteShortIntegerLongFloat, and Double classes—provide static methods for parsing strings. For example, Integer has a parseInteger method with the following signature.
public static int parseInt(String s) throws NumberFormatException
This method parses a String and returns an int. If the String does not contain a valid integer representation, a NumberFormatException is thrown.
For example, the following snippet uses parseInt to parse the string “123” to 123.
int x = Integer.parseInt("123");
Similarly, Byte provides a parseByte method, Long a parseLong method, Short a parseShort method, Float a parseFloat method, and Double a parseDouble method.
For example, the NumberTest class in Listing 8.1 takes user input and parses it. If the user types in an invalid number, an error message will be displayed.
Listing 8.1: Parsing numbers (NumberTest.java)
package app08;
import java.util.Scanner;
public class NumberTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String userInput = scanner.next();
        try {
            int i = Integer.parseInt(userInput);
            System.out.println("The number entered: " + i);
        } catch (NumberFormatException e) {
            System.out.println("Invalid user input");
        }
    }
}
Number Formatting
Number formatting helps make numbers more readable. For example, 1000000 is more readable if printed as 1,000,000 (or 1.000.000 if your locale uses . to separate the thousands). For number formatting Java offers the java.text.NumberFormat class, which is an abstract class. Since it is abstract, you cannot create an instance using the new keyword. Instead, you instantiate its subclass java.text.DecimalFormat, which is a concrete implementation of NumberFormat.
NumberFormat nf = new DecimalFormat();
However, you should not call the DecimalFormat class's constructor directly. Instead, use the the NumberFormat class's getInstance static method. This method may return an instance ofDecimalFormat but might also return an instance of a subclass other than DecimalFormat.
Now, how do you use NumberFormat to format numbers, such as 1234.56? Easy, simply pass the numbers to its format method and you'll get a String. However, should number 1234.56 be formatted as 1,234.56 or 1234,56? Well, it really depends in which side of the Atlantic you live. If you are in the US, you may want 1,234.56. If you live in Germany, however, 1234,56 makes more sense. Therefore, before you start using the format method, you want to make sure you get the correct instance of NumberFormat by telling it where you live, or, actually, in what locale you want it formatted. In Java, a locale is represented by the java.util.Locale class, which I'll explain in Chapter 19, “Internationalization.” For now, remember that the getInstance method of the NumberFormat class also has an overload that accepts a java.util.Locale.
public NumberFormat getInstance(java.util.Locale locale)
If you pass Locale.Germany to the method, you'll get a NumberFormat object that formats numbers according to the German locale. If you pass Locale.US, you'll obtain one for the US number format. The no-argument getInstance method returns a NumberFormat object with the user's computer locale.
Listing 8.2 shows the NumberFormatTest class that demonstrates how to use the NumberFormat class to format a number.
Listing 8.2: The NumberFormatTest class
package app08;
import java.text.NumberFormat;
import java.util.Locale;
public class NumberFormatTest {
    public static void main(String[] args) {
        NumberFormat nf = NumberFormat.getInstance(Locale.US);
        System.out.println(nf.getClass().getName());
        System.out.println(nf.format(123445));
    }
}
When run, the output of the execution is
java.text.DecimalFormat
123,445
The first output line shows that a java.text.DecimalFormat object was produced upon calling NumberFormat.getInstance. The second shows how the NumberFormat formats the number 123445 into a more readable form.
Number Parsing with java.text.NumberFormat
You can use the parse method of NumberFormat to parse numbers. One of this method's overloads has the following signature:
public java.lang.Number parse(java.lang.String source)
        throws ParseException
Note that parse returns an instance of java.lang.Number, the parent of such classes as IntegerLong, etc.
The java.lang.Math Class
The Math class is a utility class that provides static methods for mathematical operations. There are also two static final double fields: E and PIE represents the base of natural logarithms (e). Its value is close to 2.718. PI is the ratio of the circumference of a circle to its diameter (pi). Its value is 22/7 or approximately 3.1428.
Some of the methods in the Math class are given below.
public static double abs(double a)
Returns the absolute value of the specified double..
public static double acos(double a)
Returns the arc cosine of an angle, in the range of 0.0 through pi.
public static double asin(double a)
Returns the arc sine of an angle, in the range of −pi/2 through pi/2.
public static double atan(double a)
Returns the arc tangent of an angle, in the range of −pi/2 through pi/2.
public static double cos(double a)
Returns the cosine of an angle.
public static double exp(double a)
Returns Euler's number e raised to the power of the specified double.
public static double log(double a)
Returns the natural logarithm (base e) of the specified double.
public static double log10(double a)
Returns the base 10 logarithm of the specified double.
public static double max(double a, double b)
Returns the greater of the two specified double values.
public static double min(double a, double b)
Returns the smaller of the two specified double values.
The java.util.Date Class
There are at least two classes to use when working with dates and times. The first is java.util.Date, a class normally used to represent dates and times. The second is java.util.Calendar, often used for manipulating dates. In addition, times can also be represented as a long. See the discussion of the currentTimeMillis method of the java.lang.System class in Chapter 5, “Core Classes.”
Date has two constructors that you can safely use (the other constructors are deprecated):
public Date()
public Date(long time)
The no-arg constructor creates a Date representing the current date and time. The second constructor creates a Date that represents the specified number of milliseconds since January 1, 1970, 00:00:00 GMT.
The Date class features several useful methods, two of them are after and before.
public boolean after(Date when)
 
public boolean before(Date when)
The after method returns true if this date is a later time than the when argument. Otherwise, it returns false. The before method returns true if this date is before the specified date and returns false otherwise.
For example, the following code prints “date1 before date2” because the first date represents a time that is one millisecond earlier than the second.
Date date1 = new Date(1000);
Date date2 = new Date(1001);
if (date1.before(date2)) {
    System.out.println("date1 before date2");
} else {
    System.out.println("date1 not before date2");
}
Many of the methods in Date, such as getDategetMonthgetYear, are deprecated. You should not use these methods. Instead, use similar methods in the java.util.Calendar class.
The java.util.Calendar Class
The java.util.Date class has methods that allow you to construct a Date object from date components, such as the day, month, and year. However, these methods are deprecated. You should use java.util.Calendar instead.
To obtain a Calendar object, use one of the two static getInstance methods. Here are their signatures:
public static Calendar getInstance()
 
public static Calendar getInstance(Locale locale)
The first overload returns an instance that employs the computer's locale.
There's a lot you can do with a Calendar. For example, you can call its getTime method to obtain a Date object. Here is its signature:
public final Date getTime();
The resulting Date object, needless to say, contains components you initially passed to construct the Calendar object. In other words, if you construct a Calendar object that represents May 7, 2000 00:00:00, the Date object obtained from its getTime method will also represent May 7, 2000 00:00:00.
To obtain a date part, such as the hour, the month, or the year, use the get method. A first glance at its signature does not reveal much on how to use this method.
public int get(int field)
To use it, pass a valid field to the get method. A valid field is one of the following values: Calendar.YEARCalendar.MONTHCalendar.DATECalendar.HOUR,Calendar.MINUTECalendar.SECOND, and Calendar.MILLISECOND.
get(Calendar.YEAR) returns an int representing the year. If it is year 2010, you get 2010. get(Calendar.MONTH) returns a zero-based index of the month, with 0 representing January and 11 representing December. The others (get(Calendar.DATE)get(Calendar.HOUR), and so on) return a number representing the date/time unit.
The last thing worth mentioning: if you already have a Date object and want to make use of the methods in Calendar, you can construct a Calendar object by using the setTimemethod:
public void setTime(Date date)
Here is an example:
// myDate is a Date
Calendar calendar = Calendar.getInstance();
calendar.setTime(myDate);
To change a date/time component, call its set method:
public void set(int field, int value)
For example, to change the month component of a Calendar object to December, write this.
calendar.set(Calendar.MONTH, Calendar.DECEMBER)
There are also set method overloads for changing multiple components at the same time:
public void set(int year, int month, int date)
public void set(int year, int month, int date,
        int hour, int minute, int second)
Date Parsing and Formatting with DateFormat
Java's answer to date parsing and formatting is the java.text.DateFormat and java.text.SimpleDateFormat classes. DateFormat is an abstract class with static getInstance methods that allows you to obtain an instance of a subclass. SimpleDateFormat is a concrete implementation of DateFormat that is easier to use than its parent. This section covers both classes.
DateFormat
DateFormat supports styles and patterns. There are four styles for formatting a Date. Each style is represented by an int value. The four int fields that represent the styles are:
images DateFormat.SHORT. For example, 12/2/11
images DateFormat.MEDIUM. For example, Dec 2, 2011
images DateFormat.LONG. For example, December 2, 2011
images DateFormat.FULL. For example, Friday, December 2, 2011

When you create a DateFormat, you need to decide which style you will be using for parsing or formatting. You cannot change a DateFormat's style once you create it, but you can definitely have multiple instances of DateFormat that support different styles.
To obtain a DateFormat instance, call this static method.
public static DateFormat getDateInstance(int style)
where style is one of DateFormat.SHORTDateFormat.MEDIUMDateFormat.Long, or DateFormat.FULL. For example, the following code creates a DateFormat instance having the MEDIUM style.
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM)
To format a Date object, call its format method:
public final java.lang.String format(java.util.Date date)
To parse a string representation of a date, use the parse method. Here is the signature of parse.
public java.util.Date parse(java.lang.String date)
        throws ParseException
Note that you must compose your string according to the style of the DateFormat.
Listing 8.3 shows a class that parses and formats a date.
Listing 8.3: The DateFormatTest class
package app08;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
public class DateFormatTest {
    public static void main(String[] args) {
        DateFormat shortDf =
                DateFormat.getDateInstance(DateFormat.SHORT);
        DateFormat mediumDf =
                DateFormat.getDateInstance(DateFormat.MEDIUM);
        DateFormat longDf =
                DateFormat.getDateInstance(DateFormat.LONG);
        DateFormat fullDf =
                DateFormat.getDateInstance(DateFormat.FULL);
        System.out.println(shortDf.format(new Date()));
        System.out.println(mediumDf.format(new Date()));
        System.out.println(longDf.format(new Date()));
        ySstem.out.println(fullDf.format(new Date()));
 
        // parsing
        try {
            Date date = shortDf.parse("12/12/2006");
        } catch (ParseException e) {
        }
    }
}
Another point to note when working with DateFormat (and SimpleDateFormat) is leniency. Leniency refers to whether or not a strict rule will be applied at parsing. For example, if aDateFormat is lenient, it will accept this String: Jan 32, 2011, despite the fact that such a date does not exist. In fact, it will take the liberty of converting it to Feb 1, 2011. If a DateFormatis not lenient, it will not accept dates that do not exist. By default, a DateFormat object is lenient. The isLenient method and setLenient method allow you to check a DateFormat's leniency and change it.
public boolean isLenient()
 
public void setLenient(boolean value)
SimpleDateFormat
SimpleDateFormat is more powerful than DateFormat because you can use your own date patterns. For example, you can format and parse dates in dd/mm/yyyy, mm/dd/yyyy, yyyy-mm-dd, and so on. All you need to do is pass a pattern to a SimpleDateFormat constructor.
SimpleDateFormat is a better choice than DateFormat especially for parsing. Here is one of the constructors in SimpleDateFormat.
public SimpleDateFormat(java.lang.String pattern)
        throws java.lang.NullPointerException,
        java.lang.IllegalArgumentException
The complete rules for a valid pattern can be read in the Javadoc for the SimpleDateFormat class. The more commonly used patterns can be used by a combination of y (representing a year digit), M (representing a month digit) and d (representing a date digit). Examples of patterns are dd/MM/yyyy, dd-MM-yyyy, MM/dd/yyyy, yyyy-MM-dd.
Listing 8.4 shows a class that uses SimpleDateFormat for parsing and formatting.
Listing 8.4: The SimpleDateFormatTest class
package app08;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatTest {
    public static void main(String[] args) {
        String pattern = "MM/dd/yyyy";
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        try {
            Date date = format.parse("12/31/2011");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        // formatting
        System.out.println(format.format(new Date()));
    }
}
Summary
In Java you use primitives and wrapper classes to represent number and the java.util.Date class to represents dates. There are three types of operations that you frequently perform when dealing with number and dates: parsing, formatting and manipulation. This chapter showed how to perform them.
Number parsing is achieved through the use of the parseXXX methods in wrapper classes, such as parseInteger in java.lang.Integer and parseLong in java.lang.Long. Thejava.text.NumberFormat class can be used for number parsing and number formatting. For complex mathematical operations, use the static methods in java.lang.Math.
Date manipulation, on the other hand, is best done with the help of the java.util.Calendar class. Date parsing and formatting can be performed by using the java.text.DateFormat and the java.text.SimpleDateFormat classes.
Questions
1. What can you do with the java.lang.Math class's static methods?
2. What do you use to represents dates?

3. What class should you use if you want to define you own date pattern?

0 comments:

Post a Comment