I18N

1) What is Unicode?
Unicode provides a standard encoding for the character sets of different languages. The encoding is independent of the platform, program, or language used to access said data. Visit the Unicode Consortium (http://www.unicode.org) to learn more about Unicode developments.

2) How can I get the number of days that have elapsed between two Date objects?
That depends on what you mean by "between".
If you want to find out the number of 24-hour periods between two Date objects d1 and d2 (d2 > d1) then you would do this:


double days = (d2.getTime()-d1.getTime())/1000/60/60/24;


Since Date.getTime returns milliseconds, you divide by 1000 to get seconds, by 60 to get minutes, by 60 again to get hours, and by 24 to get days.

Sometimes this can cause difficulties, especially in countries that have a form of daylight savings time. For example, in the U.S., there is one day in the Fall which has 25 hours, and one day in the Spring which has 23 hours. An elapsed-number-of-days calculation on Dates falling on one of these days may not give the answer you expect.

Anyway, that's the easy way, and if you're satisfied with that, then read no further.

If, on the other hand, you mean the number of midnight-crossings (so that the number of days elapsed between 11:00 PM and 1:00 AM the next day is 1) then you're better off using the Calendar class and computing the Julian Day.

By the way, don't mistake the Julian Day for the Julian Calendar. The two are different and named after different "Julians".

The Julian Day is defined as the number of days elapsed since Nov 24, 4714 BC, 12:00 GMT Gregorian. The year was chosen as being sufficiently in the past so as not to have negative Julian Days, the date was chosen because of the (in that year) 37-day difference between the Julian and Gregorian calendars (Nov 24, 4714 BC Gregorian would be Jan 1, 4713 BC Julian), and the time was chosen because astronomers do their work at night, and it would be a little confusing (to them) to have the Julian Day change in the middle of their work. (I could be wrong)

Anyway, the algorithm for computing the Julian Day from a Gregorian or Julian calendar date for years 400 AD and above is as follows:

Let the date be Y, M, D, where Y is the AD year, M is the month (January=1, December=12), and D is the day (1-31).

For the following calculations, use integer arithmetic (i.e. lop off the fractional part of any result).


If M==1 or M==2 then Y--, M+=12.
Let A = Y/100
Let B = A/4
Let C = 2-A-B (or C=0 if you're using the Julian calendar)
Let E = 365.25*(Y+4716)
Let F = 30.6001*(M+1)

Julian Day = C+D+E+F-1524.5


There would be a further adjustment for the time of day, but we're not looking at that. If you want your Julian Days to start at midnight, subtract 1524 rather than 1524.5.

And so, your number-of-days-elapsed calculation would look like this:


Calendar c1 = new GregorianCalendar ();
Calendar c2 = new GregorianCalendar();

c1.setTime (d1);
c2.setTime (d2);

long j1 = julian_day(c1.get(YEAR),
c1.get(MONTH)+1, c1.get(DAY));
long j2 = julian_day(c2.get(YEAR),
c2.get(MONTH)+1, c2.get(DAY));

long days_elapsed = j2-j1;


And this would properly calculate the number of midnight-crossings between 11:00 PM on one day and 1:00 AM the next day.

You can get a little more information about the Julian Day calculations here.

You can get much more information about different calendar systems here, here, and here.


3) What is a ResourceBundle and what it is used for?
A ResourceBundle is like a specialized form of a Hashtable that maps strings to values. That doesn't sound too exciting by itself, but the magic of ResourceBundle allows you to have different lookup tables based upon what Locale (language/country) a user is coming in from. And, if a setting doesn't change between languages/countries, there is no need to repeat the setting in the customized bundle, as the runtime will search through several bundles until it finds a mapping (though in theory it could find none). Resource bundles also support another level of variants beyond language/country, such that you can have customized labels/messages for people in California and New York.

4) How can I get yesterday's date?
// get Calendar with current date
java.util.GregorianCalendar gCal =
new GregorianCalendar();

// get yesterday's date
gCal.add( Calendar.DATE, -1 );

// get components of yesterday's date
String sMonth = ( gCal.get( Calendar.MONTH ) + 1 ) + "";
String sDay = gCal.get( Calendar.DATE ) + "";
String sYear = gCal.get( Calendar.YEAR ) + "";

// get yesterday's date in milliseconds
long lMillis = gCal.getTime().getTime();

5) How do I display and parse a date?
The Java I18N way is to use a DateFormat. While SimpleDateFormat, which is generally returned, creates a large number of objects, it is locale aware and will handle most of your needs. The following sample code initially creates a java.sql.Date object and formats it for the default locale. An initial actionPerformed call additionally formats/displays it for a German locale and also displays the resulting java.sql.Date in standard escape format. Other dates can be entered and parsed after the initial display.

// JDFDP.java - Display and Parse java.sql.Date

import java.sql.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;

public class JDFDP extends JFrame
implements ActionListener,
WindowListener
{
// create a java.sql.Date
java.sql.Date jsqlDate = new java.sql.Date(
System.currentTimeMillis() );

DateFormat dfLocal = DateFormat.getDateInstance(
DateFormat.SHORT );
DateFormat dfGermany = DateFormat.getDateInstance(
DateFormat.SHORT, Locale.GERMANY );

JButton jb = new JButton( "Go" );
JLabel jlI = new JLabel("Input a Date:"),
jlD = new JLabel("Display German:"),
jlP = new JLabel("Parsed:");

JPanel jp = new JPanel();

JTextField jtI = new JTextField( 10 ),
jtD = new JTextField( 10 ),
jtP = new JTextField( 10 );


public JDFDP()
{
super( "JDFDP" );
addWindowListener( this );

jb.addActionListener( this );

jp.add(jlI);
jp.add(jtI);
jp.add(jb);
jp.add(jlD);
jp.add(jtD);
jp.add(jlP);
jp.add(jtP);

getContentPane().add( jp, BorderLayout.CENTER );
pack();

// set text by sending dummy event
jtI.setText( dfLocal.format( jsqlDate ) );
actionPerformed(
new ActionEvent( this, 12, "12" ) );

show();

} // end constructor


// ActionListener Implementation
public void actionPerformed(ActionEvent e)
{
jtD.setText( "" );
jtP.setText( "" );
try
{
java.util.Date d = dfLocal.parse(
jtI.getText() );
jtI.setText( dfLocal.format( d ) );
jtD.setText( dfGermany.format( d ) );
d = dfGermany.parse( jtD.getText() );
// get new java.sql.Date
jsqlDate = new java.sql.Date( d.getTime() );

jtP.setText( jsqlDate.toString() );
}
catch( ParseException pe ) { jtI.setText( "" ); }

} // End actionPerformed


// Window Listener Implementation
public void windowOpened(WindowEvent e) {}
public void windowClosing(WindowEvent e)
{
dispose();
System.exit(0);
}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
// End Window Listener Implementation


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

} // end class JDFDP

No comments: