1. /* ===========================================================
  2. * JFreeChart : a free chart library for the Java(tm) platform
  3. * ===========================================================
  4. *
  5. * (C) Copyright 2000-2004, by Object Refinery Limited and Contributors.
  6. *
  7. * Project Info: http://www.jfree.org/jfreechart/index.html
  8. *
  9. * This library is free software; you can redistribute it and/or modify it under the terms
  10. * of the GNU Lesser General Public License as published by the Free Software Foundation;
  11. * either version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  14. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * See the GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License along with this
  18. * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. *
  21. * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  22. * in the United States and other countries.]
  23. *
  24. * -----------
  25. * Minute.java
  26. * -----------
  27. * (C) Copyright 2001-2004, by Object Refinery Limited.
  28. *
  29. * Original Author: David Gilbert (for Object Refinery Limited);
  30. * Contributor(s): -;
  31. *
  32. * $Id: Minute.java,v 1.3 2004/11/04 11:21:54 mungady Exp $
  33. *
  34. * Changes
  35. * -------
  36. * 11-Oct-2001 : Version 1 (DG);
  37. * 18-Dec-2001 : Changed order of parameters in constructor (DG);
  38. * 19-Dec-2001 : Added a new constructor as suggested by Paul English (DG);
  39. * 14-Feb-2002 : Fixed bug in Minute(Date) constructor, and changed the range to start from zero
  40. * instead of one (DG);
  41. * 26-Feb-2002 : Changed getStart(), getMiddle() and getEnd() methods to evaluate with reference
  42. * to a particular time zone (DG);
  43. * 13-Mar-2002 : Added parseMinute() method (DG);
  44. * 19-Mar-2002 : Changed API, the minute is now defined in relation to an Hour (DG);
  45. * 10-Sep-2002 : Added getSerialIndex() method (DG);
  46. * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  47. * 10-Jan-2003 : Changed base class and method names (DG);
  48. * 13-Mar-2003 : Moved to com.jrefinery.data.time package and implemented Serializable (DG);
  49. * 21-Oct-2003 : Added hashCode() method, and new constructor for convenience (DG);
  50. * 30-Sep-2004 : Replaced getTime().getTime() with getTimeInMillis() (DG);
  51. * 04-Nov-2004 : Reverted change of 30-Sep-2004, because it won't work for JDK 1.3 (DG);
  52. *
  53. */
  54. package org.jfree.data.time;
  55. import java.io.Serializable;
  56. import java.util.Calendar;
  57. import java.util.Date;
  58. import java.util.TimeZone;
  59. /**
  60. * Represents a minute. This class is immutable, which is a requirement for
  61. * all {@link RegularTimePeriod} subclasses.
  62. */
  63. public class Minute extends RegularTimePeriod implements Serializable {
  64. /** Useful constant for the first minute in a day. */
  65. public static final int FIRST_MINUTE_IN_HOUR = 0;
  66. /** Useful constant for the last minute in a day. */
  67. public static final int LAST_MINUTE_IN_HOUR = 59;
  68. /** The hour in which the minute falls. */
  69. private Hour hour;
  70. /** The minute. */
  71. private int minute;
  72. /**
  73. * Constructs a new Minute, based on the system date/time.
  74. */
  75. public Minute() {
  76. this(new Date());
  77. }
  78. /**
  79. * Constructs a new Minute.
  80. *
  81. * @param minute the minute (0 to 59).
  82. * @param hour the hour (<code>null</code> not permitted).
  83. */
  84. public Minute(int minute, Hour hour) {
  85. if (hour == null) {
  86. throw new IllegalArgumentException("Null 'hour' argument.");
  87. }
  88. this.minute = minute;
  89. this.hour = hour;
  90. }
  91. /**
  92. * Constructs a new Minute, based on the supplied date/time.
  93. *
  94. * @param time the time (<code>null</code> not permitted).
  95. */
  96. public Minute(Date time) {
  97. // defer argument checking
  98. this(time, RegularTimePeriod.DEFAULT_TIME_ZONE);
  99. }
  100. /**
  101. * Constructs a new Minute, based on the supplied date/time and timezone.
  102. *
  103. * @param time the time (<code>null</code> not permitted).
  104. * @param zone the time zone (<code>null</code> not permitted).
  105. */
  106. public Minute(Date time, TimeZone zone) {
  107. if (time == null) {
  108. throw new IllegalArgumentException("Null 'time' argument.");
  109. }
  110. if (zone == null) {
  111. throw new IllegalArgumentException("Null 'zone' argument.");
  112. }
  113. Calendar calendar = Calendar.getInstance(zone);
  114. calendar.setTime(time);
  115. int min = calendar.get(Calendar.MINUTE);
  116. this.minute = min;
  117. this.hour = new Hour(time, zone);
  118. }
  119. /**
  120. * Creates a new minute.
  121. *
  122. * @param minute the minute (0-59).
  123. * @param hour the hour (0-23).
  124. * @param day the day (1-31).
  125. * @param month the month (1-12).
  126. * @param year the year (1900-9999).
  127. */
  128. public Minute(int minute,
  129. int hour,
  130. int day,
  131. int month,
  132. int year) {
  133. this(minute, new Hour(hour, new Day(day, month, year)));
  134. }
  135. /**
  136. * Returns the hour.
  137. *
  138. * @return The hour (never <code>null</code>).
  139. */
  140. public Hour getHour() {
  141. return this.hour;
  142. }
  143. /**
  144. * Returns the minute.
  145. *
  146. * @return The minute.
  147. */
  148. public int getMinute() {
  149. return this.minute;
  150. }
  151. /**
  152. * Returns the minute preceding this one.
  153. *
  154. * @return The minute preceding this one.
  155. */
  156. public RegularTimePeriod previous() {
  157. Minute result;
  158. if (this.minute != FIRST_MINUTE_IN_HOUR) {
  159. result = new Minute(this.minute - 1, this.hour);
  160. }
  161. else { // we are at the first minute in the hour...
  162. Hour prevHour = (Hour) this.hour.previous();
  163. if (prevHour != null) {
  164. result = new Minute(LAST_MINUTE_IN_HOUR, prevHour);
  165. }
  166. else {
  167. result = null;
  168. }
  169. }
  170. return result;
  171. }
  172. /**
  173. * Returns the minute following this one.
  174. *
  175. * @return The minute following this one.
  176. */
  177. public RegularTimePeriod next() {
  178. Minute result;
  179. if (this.minute != LAST_MINUTE_IN_HOUR) {
  180. result = new Minute(this.minute + 1, this.hour);
  181. }
  182. else { // we are at the last minute in the hour...
  183. Hour nextHour = (Hour) this.hour.next();
  184. if (nextHour != null) {
  185. result = new Minute(FIRST_MINUTE_IN_HOUR, nextHour);
  186. }
  187. else {
  188. result = null;
  189. }
  190. }
  191. return result;
  192. }
  193. /**
  194. * Returns a serial index number for the minute.
  195. *
  196. * @return The serial index number.
  197. */
  198. public long getSerialIndex() {
  199. return this.hour.getSerialIndex() * 60L + this.minute;
  200. }
  201. /**
  202. * Returns the first millisecond of the minute.
  203. *
  204. * @param calendar the calendar (which defines the timezone).
  205. *
  206. * @return The first millisecond.
  207. */
  208. public long getFirstMillisecond(Calendar calendar) {
  209. int year = this.hour.getDay().getYear();
  210. int month = this.hour.getDay().getMonth() - 1;
  211. int day = this.hour.getDay().getDayOfMonth();
  212. calendar.clear();
  213. calendar.set(year, month, day, this.hour.getHour(), this.minute, 0);
  214. calendar.set(Calendar.MILLISECOND, 0);
  215. //return calendar.getTimeInMillis(); // this won't work for JDK 1.3
  216. return calendar.getTime().getTime();
  217. }
  218. /**
  219. * Returns the last millisecond of the minute.
  220. *
  221. * @param calendar the calendar and timezone.
  222. *
  223. * @return The last millisecond.
  224. */
  225. public long getLastMillisecond(Calendar calendar) {
  226. int year = this.hour.getDay().getYear();
  227. int month = this.hour.getDay().getMonth() - 1;
  228. int day = this.hour.getDay().getDayOfMonth();
  229. calendar.clear();
  230. calendar.set(year, month, day, this.hour.getHour(), this.minute, 59);
  231. calendar.set(Calendar.MILLISECOND, 999);
  232. //return calendar.getTimeInMillis(); // this won't work for JDK 1.3
  233. return calendar.getTime().getTime();
  234. }
  235. /**
  236. * Tests the equality of this object against an arbitrary Object.
  237. * <P>
  238. * This method will return true ONLY if the object is a Minute object
  239. * representing the same minute as this instance.
  240. *
  241. * @param obj the object to compare (<code>null</code> permitted).
  242. *
  243. * @return <code>true</code> if the minute and hour value of this and the
  244. * object are the same.
  245. */
  246. public boolean equals(Object obj) {
  247. if (obj == this) {
  248. return true;
  249. }
  250. if (!(obj instanceof Minute)) {
  251. return false;
  252. }
  253. Minute that = (Minute) obj;
  254. if (this.minute != that.minute) {
  255. return false;
  256. }
  257. if (!this.hour.equals(that.hour)) {
  258. return false;
  259. }
  260. return true;
  261. }
  262. /**
  263. * Returns a hash code for this object instance.
  264. * <p>
  265. * The approach described by Joshua Bloch in "Effective Java" has been used here:
  266. * <p>
  267. * <code>http://developer.java.sun.com/developer/Books/effectivejava/Chapter3.pdf</code>
  268. *
  269. * @return A hash code.
  270. */
  271. public int hashCode() {
  272. int result = 17;
  273. result = 37 * result + this.minute;
  274. result = 37 * result + this.hour.hashCode();
  275. return result;
  276. }
  277. /**
  278. * Returns an integer indicating the order of this Minute object relative
  279. * to the specified object:
  280. *
  281. * negative == before, zero == same, positive == after.
  282. *
  283. * @param o1 object to compare.
  284. *
  285. * @return negative == before, zero == same, positive == after.
  286. */
  287. public int compareTo(Object o1) {
  288. int result;
  289. // CASE 1 : Comparing to another Minute object
  290. // -------------------------------------------
  291. if (o1 instanceof Minute) {
  292. Minute m = (Minute) o1;
  293. result = getHour().compareTo(m.getHour());
  294. if (result == 0) {
  295. result = this.minute - m.getMinute();
  296. }
  297. }
  298. // CASE 2 : Comparing to another TimePeriod object
  299. // -----------------------------------------------
  300. else if (o1 instanceof RegularTimePeriod) {
  301. // more difficult case - evaluate later...
  302. result = 0;
  303. }
  304. // CASE 3 : Comparing to a non-TimePeriod object
  305. // ---------------------------------------------
  306. else {
  307. // consider time periods to be ordered after general objects
  308. result = 1;
  309. }
  310. return result;
  311. }
  312. /**
  313. * Creates a Minute instance by parsing a string. The string is assumed to
  314. * be in the format "YYYY-MM-DD HH:MM", perhaps with leading or trailing
  315. * whitespace.
  316. *
  317. * @param s the minute string to parse.
  318. *
  319. * @return <code>null</code>, if the string is not parseable, the minute
  320. * otherwise.
  321. */
  322. public static Minute parseMinute(String s) {
  323. Minute result = null;
  324. s = s.trim();
  325. String daystr = s.substring(0, Math.min(10, s.length()));
  326. Day day = Day.parseDay(daystr);
  327. if (day != null) {
  328. String hmstr = s.substring(Math.min(daystr.length() + 1, s.length()), s.length());
  329. hmstr = hmstr.trim();
  330. String hourstr = hmstr.substring(0, Math.min(2, hmstr.length()));
  331. int hour = Integer.parseInt(hourstr);
  332. if ((hour >= 0) && (hour <= 23)) {
  333. String minstr = hmstr.substring(
  334. Math.min(hourstr.length() + 1, hmstr.length()), hmstr.length()
  335. );
  336. int minute = Integer.parseInt(minstr);
  337. if ((minute >= 0) && (minute <= 59)) {
  338. result = new Minute(minute, new Hour(hour, day));
  339. }
  340. }
  341. }
  342. return result;
  343. }
  344. }