/* * [TZ.java] * * Summary: TZ display TimeZones supported on your computer with their offsets from GMT. * * Copyright: (c) 2004-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.1 2005-06-30 add stomp bat files * 1.2 2005-07-27 add main method * 1.3 2006-03-05 reformat with IntelliJ and and Javadoc * 1.4 2007-08-08 add default TZ display, convert to JDK 1.5, add time display. * add live local time display. * 1.5 2007-08-08 add utc time display, sort by offset and id. * 1.6 2007-10-09 utc time display, in 24-hour time. * 1.7 2008-04-05 add build to title. * 1.8 2008-04-27 make columns sortable. * 1.9 2008-06-13 flip to JDK 1.6 to allow access to TableRowSorter */ package com.mindprod.tz; import com.mindprod.common18.Build; import com.mindprod.common18.CMPAboutJBox; import com.mindprod.common18.Common18; import com.mindprod.common18.FontFactory; import com.mindprod.common18.HybridJ; import com.mindprod.common18.JEButton; import com.mindprod.common18.VersionCheck; import javax.swing.BorderFactory; import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.Timer; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; /** * TZ display TimeZones supported on your computer with their offsets from GMT. * * @author Roedy Green, Canadian Mind Products * @version 1.9 2008-06-13 flip to JDK 1.6 to allow access to TableRowSorter * @since 2004 */ @SuppressWarnings( { "FieldCanBeLocal" } ) public final class TZ extends JApplet { /** * height of Applet box in pixels. Does not include surrounding frame. */ private static final int APPLET_HEIGHT = 645; /** * Width of Applet box in pixels. */ private static final int APPLET_WIDTH = 822; private static final int FIRST_COPYRIGHT_YEAR = 2004; /** * undisplayed copyright notice */ @SuppressWarnings( { "UnusedDeclaration" } ) private static final String EMBEDDED_COPYRIGHT = "Copyright: (c) 2004-2017 Roedy Green, Canadian Mind Products, http://mindprod.com"; private static final String RELEASE_DATE = "2008-06-13"; private static final String TITLE_STRING = "TimeZones"; private static final String VERSION_STRING = "1.9"; /** * pale violet blue */ private static final Color BACKGROUND_FOR_APPLET = new Color( 0xd4d4ff ); private static final Color FOREGROUND_FOR_INSTRUCTIONS = new Color( 0x008000 ); private static final Color FOREGROUND_FOR_LABEL = new Color( 0x0000b0 ); /** * for titles */ private static final Color FOREGROUND_FOR_TITLE = new Color( 0xdc143c ); /** * pick noon 2007-06-21 0:00 as a typical summer day that likely will be using DST. */ private static final Date aSummerDay = new GregorianCalendar( 2007, Calendar.JUNE, 21 ).getTime(); /** * pick 2007-06-21 0::00 as a typical winter day that will not be using DST. */ private static final Date aWinterDay = new GregorianCalendar( 2007, Calendar.DECEMBER, 21 ).getTime(); /** * for for titles and About buttons */ private static final Font FONT_FOR_TITLE = FontFactory.build( "Dialog", Font.BOLD, 16 ); /** * for for title second line */ private static final Font FONT_FOR_TITLE2 = FontFactory.build( "Dialog", Font.PLAIN, 14 ); /** * zz=PDT zzzz="pacific Daylight Time" EEEE=dow hh=12 hour */ private static final SimpleDateFormat localTimeDisplay = new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss aa zz : zzzzzz EEEE" ); /** * zz=PDT zzzz="pacific Daylight Time" EEEE=dow HH=24 hour */ private static final SimpleDateFormat utcTimeDisplay = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss zz : zzzzzz EEEE" ); private static final int[] PREFERRED_COLUMN_WIDTH = { 45, 45, 215, 330 }; static { utcTimeDisplay.setTimeZone( TimeZone.getTimeZone( "UTC" ) ); } private JButton about; private JLabel instructions; private JLabel localTimeLabel; private JLabel localTZLabel; private JLabel supportedLabel; private JLabel title; /** * title, second line */ private JLabel title2; private JLabel utcTimeLabel; /** * scroll the JTable of TimeZones */ private JScrollPane scroller; /** * grid of TimeZone data */ private JTable timeZoneTable; private JTextField localTimeField; private JTextField localTZField; private JTextField utcTimeField; /** * timer to help us keep clock up to date. */ private Timer timer; /** * allocate all components */ private void buildComponents() { title = new JLabel( TITLE_STRING + " " + VERSION_STRING ); title.setFont( FONT_FOR_TITLE ); title.setForeground( FOREGROUND_FOR_TITLE ); title2 = new JLabel( "released:" + RELEASE_DATE + " build:" + Build.BUILD_NUMBER ); title2.setFont( FONT_FOR_TITLE2 ); title2.setForeground( FOREGROUND_FOR_TITLE ); about = new JEButton( "About" ); about.setToolTipText( "About " + TITLE_STRING + " " + VERSION_STRING ); about.addActionListener( new ActionListener() { /** * Method actionPerformed ... * @param e of type ActionEvent */ public void actionPerformed( ActionEvent e ) { // open aboutbox frame new CMPAboutJBox( TITLE_STRING, VERSION_STRING, "Display all Timezones that Java supports on this machine.", "", "freeware", RELEASE_DATE, FIRST_COPYRIGHT_YEAR, "Roedy Green", "TZ", "1.8" ); } } ); utcTimeLabel = new JLabel( "UTC" ); utcTimeLabel.setForeground( FOREGROUND_FOR_LABEL ); utcTimeField = new JTextField( localTimeDisplay.format( new Date() ) ); utcTimeField.setEditable( false ); localTimeLabel = new JLabel( "local time" ); localTimeLabel.setForeground( FOREGROUND_FOR_LABEL ); localTimeField = new JTextField( localTimeDisplay.format( new Date() ) ); localTimeField.setEditable( false ); localTZLabel = new JLabel( "local TZ" ); localTZLabel.setForeground( FOREGROUND_FOR_LABEL ); localTZField = new JTextField( TimeZone.getDefault().getDisplayName() ); localTZField.setEditable( false ); supportedLabel = new JLabel( "Supported TimeZones", JLabel.CENTER ); supportedLabel.setForeground( FOREGROUND_FOR_LABEL ); final String[] allTimeZoneIDs = TimeZone.getAvailableIDs(); Arrays.sort( allTimeZoneIDs, new ByOffset() ); final TZTableModel model = new TZTableModel( allTimeZoneIDs ); timeZoneTable = new JTable( model ); // set some initial column widths final TableColumnModel tableColumnModel = timeZoneTable.getColumnModel(); // give a bit more space between columns tableColumnModel.setColumnMargin( 5 ); // hook up our HeaderRenderer to all four columns // and set preferred width in pixels for each column. final TableCellRenderer headerRenderer = new HeaderRenderer(); for ( int i = 0; i < 4; i++ ) { final TableColumn tableColumn = tableColumnModel.getColumn( i ); tableColumn.setHeaderRenderer( headerRenderer ); tableColumn.setPreferredWidth( PREFERRED_COLUMN_WIDTH[ i ] ); } scroller = new JScrollPane( timeZoneTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED ); // this is all you need to make every column sortable ascending/descending by clicking on the heading. timeZoneTable.setRowSorter( new TableRowSorter<>( model ) ); instructions = new JLabel( "Click column heading to sort.", JLabel.CENTER ); instructions.setForeground( FOREGROUND_FOR_INSTRUCTIONS ); } private void layoutComponents( Container contentPane ) { // ---0-----1-----2--------3-- // 0 title----- title2-- about // ~time time---------------- // ~default default----------- // ~ supported---------------- // jtable -------------------- // instructions--------------- // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( title, new GridBagConstraints( 0, 0, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 10, 10, 5, 5 ), 0, 0 ) ); contentPane.add( title2, new GridBagConstraints( 2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 10, 5, 5, 5 ), 0, 0 ) ); contentPane.add( about, new GridBagConstraints( 3, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 10, 5, 5, 10 ), 0, 0 ) ); contentPane.add( utcTimeLabel, new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 10, 10, 0, 5 ), 0, 0 ) ); contentPane.add( utcTimeField, new GridBagConstraints( 1, 1, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 10, 5, 0, 10 ), 0, 0 ) ); contentPane.add( localTimeLabel, new GridBagConstraints( 0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 10, 10, 0, 5 ), 0, 0 ) ); contentPane.add( localTimeField, new GridBagConstraints( 1, 2, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 10, 5, 0, 10 ), 0, 0 ) ); contentPane.add( localTZLabel, new GridBagConstraints( 0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 10, 10, 0, 5 ), 0, 0 ) ); contentPane.add( localTZField, new GridBagConstraints( 1, 3, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 10, 5, 0, 10 ), 0, 0 ) ); contentPane.add( supportedLabel, new GridBagConstraints( 0, 4, 3, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets( 10, 10, 0, 10 ), 0, 0 ) ); contentPane.add( scroller, new GridBagConstraints( 0, 5, 4, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets( 10, 10, 10, 10 ), 0, 0 ) ); contentPane.add( instructions, new GridBagConstraints( 0, 6, 4, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets( 10, 10, 10, 10 ), 0, 0 ) ); } /** * Allow this Applet to run as as application as well. * * @param args command line arguments ignored. */ public static void main( String args[] ) { HybridJ.fireup( new TZ(), TITLE_STRING + " " + VERSION_STRING, APPLET_WIDTH, APPLET_HEIGHT ); } // end main /** * Called by the browser or Applet viewer to inform * this Applet that it is being reclaimed and that it should destroy * any resources that it has allocated. */ public void destroy() { about = null; instructions = null; localTimeField = null; localTimeLabel = null; localTZField = null; localTZLabel = null; scroller = null; supportedLabel = null; timer = null; timeZoneTable = null; title2 = null; title = null; utcTimeField = null; utcTimeLabel = null; } /** * Called by the browser or Applet viewer to inform * this Applet that it has been loaded into the system. */ @Override public void init() { if ( !VersionCheck.isJavaVersionOK( 1, 8, 0, this ) ) { return; } Common18.setLaf(); Container contentPane = this.getContentPane(); contentPane.setBackground( BACKGROUND_FOR_APPLET ); contentPane.setLayout( new GridBagLayout() ); buildComponents(); layoutComponents( contentPane ); this.validate(); } /** * usual Applet start, we start up Timer to update clock */ public void start() { timer = new Timer( 500/* every half second */, new ActionListener() { public void actionPerformed( ActionEvent e ) { // executed on Swing Thread. localTimeField.setText( localTimeDisplay.format( new Date() ) ); utcTimeField.setText( utcTimeDisplay.format( new Date() ) ); } } ); timer.setRepeats( true ); // start it ticking, timer.start(); } /** * usual Applet stop, we kill Timer to update clock */ public void stop() { timer.stop(); timer = null; } /** * Sort by TimeZone offset. *
* Defines an alternate sort order for String. */ private static class ByOffset implements ComparatorJTable
to set up a default renderer and editor for the column.
*
* @param columnIndex the index of the column
*
* @return the common ancestor class of the object values in the model.
*/
public Class> getColumnClass( int columnIndex )
{
switch ( columnIndex )
{
case 0:
case 1:
return Double.class;
case 2:
case 3:
return String.class;
default:
throw new ArrayIndexOutOfBoundsException(
"column index out of range in get ColumnClass" );
}
}
/**
* Returns the number of columns in the model. A JTable
uses this method to determine how many
* columns it should create and display by default.
*
* @return the number of columns in the model
* @see #getRowCount
*/
public int getColumnCount()
{
return 4;
}
/**
* Returns the name of the column at columnIndex
. This is used to initialize the table's column
* header name. Note: this name does not need to be unique; two columns in a table can have the same name.
*
* @param column the index of the column
*
* @return the name of the column
*/
public String getColumnName( int column )
{
return columnNames[ column ];
}
/**
* Returns the number of rows in the model. A JTable
uses this method to determine how many rows it
* should display. This method should be quick, as it is called frequently during rendering.
*
* @return the number of rows in the model
* @see #getColumnCount
*/
public int getRowCount()
{
return timeZoneIDs.length;
}
/* get value at given row and column
* @param row zero-based row number
* @param col zero-based column number
* @return Object, will be String, Integer or Float.
*/
public Object getValueAt( int rowIndex, int columnIndex )
{
final String timeZoneID = timeZoneIDs[ rowIndex ];
final TimeZone timeZone = TimeZone.getTimeZone( timeZoneID );
switch ( columnIndex )
{
case 0:
// offset in hours.
// want floating point arithmetic. Don't use TimeUnit.
return timeZone.getRawOffset() / ( 60 * 60 * 1000.0D );
case 1:
final double raw =
timeZone.getRawOffset() / ( 60
* 60
* 1000.0D );// hrs winter
final double summer =
timeZone.getOffset( aSummerDay.getTime() ) / ( 60
* 60
* 1000.0D );// millis -> hrs summer
final double winter =
timeZone.getOffset( aWinterDay.getTime() ) / ( 60
* 60
* 1000.0D );// millis -> hrs summer
// dst in hours.
return ( raw == summer ) ? winter : summer;
case 2:
return timeZoneID;
case 3:
return timeZone.getDisplayName();
default:
throw new ArrayIndexOutOfBoundsException(
"col index out of range in get getValueAt" );
}
}
}
}