001 package org.jrobin.core.timespec;
002
003 import org.jrobin.core.RrdException;
004 import org.jrobin.core.Util;
005
006 import javax.swing.*;
007 import java.awt.*;
008 import java.awt.event.ActionEvent;
009 import java.awt.event.ActionListener;
010 import java.text.ParseException;
011 import java.text.SimpleDateFormat;
012 import java.util.Date;
013
014 /**
015 * Small swing-based utility to convert timestamps (seconds since epoch) to readable dates and vice versa.
016 * Supports at-style time specification (like "now-2d", "noon yesterday") and other human-readable
017 * data formats:<p>
018 * <ul>
019 * <li>MM/dd/yy HH:mm:ss
020 * <li>dd.MM.yy HH:mm:ss
021 * <li>dd.MM.yy HH:mm:ss
022 * <li>MM/dd/yy HH:mm
023 * <li>dd.MM.yy HH:mm
024 * <li>yy-MM-dd HH:mm
025 * <li>MM/dd/yy
026 * <li>dd.MM.yy
027 * <li>yy-MM-dd
028 * <li>HH:mm MM/dd/yy
029 * <li>HH:mm dd.MM.yy
030 * <li>HH:mm yy-MM-dd
031 * <li>HH:mm:ss MM/dd/yy
032 * <li>HH:mm:ss dd.MM.yy
033 * <li>HH:mm:ss yy-MM-dd
034 * </ul>
035 * The current timestamp is displayed in the title bar :)<p>
036 */
037 public class Epoch extends JFrame {
038 private static final long serialVersionUID = 1L;
039 private static final String[] supportedFormats = {
040 "MM/dd/yy HH:mm:ss", "dd.MM.yy HH:mm:ss", "yy-MM-dd HH:mm:ss", "MM/dd/yy HH:mm",
041 "dd.MM.yy HH:mm", "yy-MM-dd HH:mm", "MM/dd/yy", "dd.MM.yy", "yy-MM-dd", "HH:mm MM/dd/yy",
042 "HH:mm dd.MM.yy", "HH:mm yy-MM-dd", "HH:mm:ss MM/dd/yy", "HH:mm:ss dd.MM.yy", "HH:mm:ss yy-MM-dd"
043 };
044
045 private static final SimpleDateFormat[] parsers = new SimpleDateFormat[supportedFormats.length];
046 private static final String helpText;
047
048 private Timer timer = new Timer(1000, new ActionListener() {
049 public void actionPerformed(ActionEvent e) {
050 showTimestamp();
051 }
052 });
053
054 static {
055 for (int i = 0; i < parsers.length; i++) {
056 parsers[i] = new SimpleDateFormat(supportedFormats[i]);
057 parsers[i].setLenient(true);
058 }
059 StringBuffer tooltipBuff = new StringBuffer("<html><b>Supported input formats:</b><br>");
060 for (String supportedFormat : supportedFormats) {
061 tooltipBuff.append(supportedFormat).append("<br>");
062 }
063 tooltipBuff.append("<b>AT-style time specification</b><br>");
064 tooltipBuff.append("timestamp<br><br>");
065 tooltipBuff.append("Copyright (C) 2003-2005 Sasa Markovic, All Rights Reserved</html>");
066 helpText = tooltipBuff.toString();
067 }
068
069 private JLabel topLabel = new JLabel("Enter timestamp or readable date:");
070 private JTextField inputField = new JTextField(25);
071 private JButton convertButton = new JButton("Convert");
072 private JButton helpButton = new JButton("Help");
073
074 private static final SimpleDateFormat OUTPUT_DATE_FORMAT =
075 new SimpleDateFormat("MM/dd/yy HH:mm:ss EEE");
076
077 Epoch() {
078 super("Epoch");
079 constructUI();
080 timer.start();
081 }
082
083 private void constructUI() {
084 JPanel c = (JPanel) getContentPane();
085 c.setLayout(new BorderLayout(3, 3));
086 c.add(topLabel, BorderLayout.NORTH);
087 c.add(inputField, BorderLayout.WEST);
088 c.add(convertButton, BorderLayout.CENTER);
089 convertButton.setToolTipText(helpText);
090 convertButton.addActionListener(new ActionListener() {
091 public void actionPerformed(ActionEvent e) {
092 convert();
093 }
094 });
095 c.add(helpButton, BorderLayout.EAST);
096 helpButton.addActionListener(new ActionListener() {
097 public void actionPerformed(ActionEvent e) {
098 JOptionPane.showMessageDialog(helpButton, helpText, "Epoch Help", JOptionPane.INFORMATION_MESSAGE);
099 }
100 });
101 inputField.requestFocus();
102 getRootPane().setDefaultButton(convertButton);
103 setResizable(false);
104 setDefaultCloseOperation(EXIT_ON_CLOSE);
105 pack();
106 centerOnScreen();
107 setVisible(true);
108 }
109
110 void centerOnScreen() {
111 Toolkit t = Toolkit.getDefaultToolkit();
112 Dimension screenSize = t.getScreenSize();
113 Dimension frameSize = getPreferredSize();
114 double x = (screenSize.getWidth() - frameSize.getWidth()) / 2;
115 double y = (screenSize.getHeight() - frameSize.getHeight()) / 2;
116 setLocation((int) x, (int) y);
117 }
118
119 private void convert() {
120 String time = inputField.getText().trim();
121 if (time.length() > 0) {
122 // try simple timestamp
123 try {
124 long timestamp = Long.parseLong(time);
125 Date date = new Date(timestamp * 1000L);
126 formatDate(date);
127 }
128 catch (NumberFormatException nfe) {
129 // failed, try as a date
130 try {
131 inputField.setText("" + parseDate(time));
132 }
133 catch (RrdException e) {
134 inputField.setText("Could not convert, sorry");
135 }
136 }
137 }
138 }
139
140 private void showTimestamp() {
141 long timestamp = Util.getTime();
142 setTitle(timestamp + " seconds since epoch");
143 }
144
145 void formatDate(Date date) {
146 inputField.setText(OUTPUT_DATE_FORMAT.format(date));
147 }
148
149 private long parseDate(String time) throws RrdException {
150 for (SimpleDateFormat parser : parsers) {
151 try {
152 return Util.getTimestamp(parser.parse(time));
153 }
154 catch (ParseException e) {
155 // NOP
156 }
157 }
158 return new TimeParser(time).parse().getTimestamp();
159 }
160
161 /**
162 * Main method which runs this utility.
163 *
164 * @param args Not used.
165 */
166 public static void main(String[] args) {
167 new Epoch();
168 }
169 }