Advertisement
Guest User

Cs12Date

a guest
Apr 7th, 2017
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.16 KB | None | 0 0
  1. /*
  2. * Name:
  3. *
  4. * Course: CS-12
  5. *
  6. * Date: 06/02/15
  7. *
  8. * Filename: CS12Date.java
  9. *
  10. * Purpose: Provides a more richly-featured version
  11. * of the (former textbook) SimpleDate.java.
  12. * Intended to be full back-compatible with that class.
  13. *
  14. * History: RNL 10/02/16: Updated print() to avoid tabbing,
  15. * problems being observed in Fall 2016 with output tabbing
  16. * between jGRASP versions.
  17. *
  18. * RNL 03/07/17: Fixed some javadoc problems involving
  19. * self-closing tag </br> with apparently newer HTML,
  20. * and also several logic symbols, replaced then with HTML sequences.
  21. */
  22.  
  23. import java.util.Calendar;
  24. import java.lang.String;
  25.  
  26. /**
  27. * Implements a M/D/Y user-annotated date with multiple date utilities,
  28. * for use in CS-12 programs.
  29. */
  30. public class CS12Date {
  31.  
  32. //=================================================================
  33. // instance variables
  34. //=================================================================
  35. private int month; // must be 1-12
  36. private int day; // must be 1-31 and correct for current month
  37. private int year; // must be > 0, always stored as YYYY
  38. private String text; // optional descriptive text
  39.  
  40. //=================================================================
  41. // constructors
  42. //=================================================================
  43.  
  44. /**
  45. * Default constructor, initializes to current date, with no annotation.
  46. */
  47. public CS12Date() {
  48. Calendar today = Calendar.getInstance();
  49.  
  50. year = today.get(Calendar.YEAR);
  51. month = today.get(Calendar.MONTH) + 1;
  52. day = today.get(Calendar.DATE);
  53. text = "";
  54. }
  55.  
  56. /**
  57. * Full constructor, allows user-specification of all fields,
  58. * any invalid numeric data defaults to that of the current date.
  59. * @param month the desired month
  60. * @param day the desired day
  61. * @param year the desired year
  62. * @param text descriptive text for the desired date
  63. */
  64. public CS12Date(int month, int day, int year, String text) {
  65. this(); // pull in defaults for all fields (current date)
  66.  
  67. // if numeric values are invalid, defaults will be retained
  68. setYear(year);
  69. setMonth(month);
  70. setDay(day);
  71. this.text = text;
  72. }
  73.  
  74. /**
  75. * Alternate constructor, sets month, day, year only,
  76. * any invalid numeric data defaults to that of the current date.
  77. * @param month the desired month
  78. * @param day the desired day
  79. * @param year the desired year
  80. */
  81. public CS12Date(int month, int day, int year) {
  82. this(); // pull in defaults for all fields (current date)
  83.  
  84. // if numeric values are invalid, defaults will be retained
  85. setYear(year);
  86. setMonth(month);
  87. setDay(day);
  88. }
  89.  
  90. /**
  91. * Alternate constructor, sets date to month and day of current year,
  92. * any invalid numeric data defaults to that of the current date.
  93. * @param month the desired month
  94. * @param day the desired day
  95. */
  96. public CS12Date(int month, int day) {
  97. this(); // pull in defaults for all fields (current date)
  98.  
  99. // if numeric values are invalid, defaults will be retained
  100. Calendar today = Calendar.getInstance();
  101.  
  102. setYear(today.get(Calendar.YEAR));
  103. setMonth(month);
  104. setDay(day);
  105. }
  106.  
  107. /**
  108. * Alternate constructor, sets date to Jan 1st of specified year,
  109. * invalid year defaults to the current year.
  110. * @param year the desired year
  111. */
  112. public CS12Date(int year) {
  113. this(); // pull in defaults for all fields (current date)
  114.  
  115. // if numeric values are invalid, defaults will be retained
  116. setYear(year);
  117. month = 1;
  118. day = 1;
  119. }
  120.  
  121. /**
  122. * Alternate constructor, sets date to current date with specified annotation,
  123. * @param text descriptive text for the desired date
  124. */
  125. public CS12Date(String text) {
  126. this(); // pull in defaults for all fields (current date)
  127.  
  128. // set desired annotation
  129. this.text = text;
  130. }
  131. //=================================================================
  132. // display methods
  133. //=================================================================
  134.  
  135. /**
  136. * Returns a standard M/D/Y string, along with any descriptive text, in a comma-separated format.
  137. * @return M/D/Y String representation of date, plus any descriptive text
  138. */
  139. public String toString() {
  140. return month + "/" + day + "/" + year + // date portion
  141. (text.length() > 0 ? (", " + text) : text); // text portion
  142. }
  143.  
  144. /**
  145. * Displays labeled output of all fields, plus some additional values AND toString() output.
  146. */
  147. public void print() {
  148. String fmtInt = "%-16s%d\n";
  149. String fmtStr = "%-16s%s\n";
  150. String fmtBool = "%-16s%b\n";
  151.  
  152. // original version: tabbing
  153. //System.out.println("year:\t\t" + year);
  154. //System.out.println("month:\t\t" + month);
  155. //System.out.println("day:\t\t" + day);
  156. //System.out.println("text:\t\t" + text);
  157. //System.out.println("toString():\t" + toString());
  158. //System.out.println("day in year:\t" + getDateNum());
  159. //System.out.println("leap year?\t" + isLeapYear(year));
  160.  
  161. // updated version: format specifiers (non-tabbing)
  162. System.out.printf(fmtInt, "year:", year);
  163. System.out.printf(fmtInt, "month:", month);
  164. System.out.printf(fmtInt, "day:", day);
  165. System.out.printf(fmtStr, "text:", text);
  166. System.out.printf(fmtStr, "toString():", toString());
  167. System.out.printf(fmtInt, "day in year:", getDateNum());
  168. System.out.printf(fmtBool, "leap year?", isLeapYear(year));
  169. }
  170.  
  171. /**
  172. * Overloaded print, adds some additional user-specified message text.
  173. * @param message message to be prepended to print()
  174. */
  175. public void print(String message) {
  176. spacer();
  177. System.out.println(message);
  178. spacer();
  179. print();
  180. spacer();
  181. }
  182.  
  183. // accessors/mutators ----------------------------------------------
  184.  
  185. /**
  186. * year mutator, sets desired year, checks that year is A.D.
  187. * @param year desired year (YYYY)
  188. */
  189. public void setYear(int year) {
  190. if (year < 0) {
  191. error("year must be >= 0, does not handle B.C., not changed");
  192. }
  193. else {
  194. this.year = year;
  195. }
  196. }
  197.  
  198. /**
  199. * year accessor, returns year
  200. * @return currently specified year
  201. */
  202. public int getYear() {
  203. return year;
  204. }
  205.  
  206. /**
  207. * month mutator, sets desired year, performs 1-12 checking on month
  208. * @param month desired month
  209. */
  210. public void setMonth(int month) {
  211. if ((month < 1) || (month > 12)) {
  212. error("month must be 1-12, not changed");
  213. }
  214. else {
  215. this.month = month;
  216. }
  217. }
  218.  
  219. /**
  220. * month accessor, returns month
  221. * @return month currently specified month
  222. */
  223. public int getMonth() {
  224. return month;
  225. }
  226.  
  227. /**
  228. * day mutator, sets desired day, checks whether day is valid for existing month/year
  229. * @param day desired day
  230. */
  231. public void setDay(int day) {
  232. int maxDays = daysInMonth(this.month, this.year);
  233. if ((day < 1) || (day > maxDays)) {
  234. error("day must be 1-" + maxDays + ", not changed");
  235. }
  236. else {
  237. this.day = day;
  238. }
  239. }
  240.  
  241. /**
  242. * day accessor, returns currently specified day
  243. * @return day currently specified day
  244. */
  245. public int getDay() {
  246. return day;
  247. }
  248.  
  249. /**
  250. * text mutator, sets an (optional) user-specified text descriptor for the date
  251. * @param text desired text
  252. */
  253. public void setText(String text) {
  254. this.text = text;
  255. }
  256.  
  257. /**
  258. * text accessor, returns (optional) currently specified text
  259. * @return text currently specified text
  260. */
  261. public String getText() {
  262. return text;
  263. }
  264.  
  265. // derived data accessors ------------------------------------------
  266.  
  267. /**
  268. * Returns the ordered date number within the year (1-365 or 1-366)
  269. * @return day number within the current year
  270. */
  271. public int getDateNum() {
  272. int dateNum = 0;
  273.  
  274. for (int i=1; i<month; i++) {
  275. dateNum += daysInMonth(i, this.year);
  276. }
  277. dateNum += day;
  278.  
  279. return dateNum;
  280. }
  281.  
  282. // specific date mutators ------------------------------------------
  283.  
  284. /**
  285. * Sets the date to a specific month/day/year date
  286. * @param month desired month
  287. * @param day desired day
  288. * @param year desired year (YYYY)
  289. */
  290. public void setDate(int month, int day, int year) {
  291. setMonth(month);
  292. setDay(day);
  293. setYear(year);
  294. }
  295.  
  296. /**
  297. * Sets the date to that of a specified ordinal date number within existing year, taking into account leap year
  298. * @param dateNum day number within the existing year
  299. */
  300. public void setDate(int dateNum) {
  301. setDate(dateNum, year);
  302. }
  303.  
  304. /**
  305. * Sets the date to that of a specified ordinal date number within a given year, taking into account leap year
  306. * @param dateNum day number within the existing year
  307. * @param year the desired year
  308. */
  309. public void setDate(int dateNum, int year) {
  310.  
  311. CS12Date temp = new CS12Date(year);
  312.  
  313. // first, error checking for invalid date numbers
  314. if (dateNum < 1) {
  315. error("date number must be >= 0, date unchanged");
  316. return;
  317. }
  318. else if ((!temp.isLeapYear(year)) && (dateNum > 365)) {
  319. error("date number must be <= 365 for a non-leap year, date unchanged");
  320. return;
  321. }
  322. else if ((temp.isLeapYear(year)) && (dateNum > 366)) {
  323. error("date number must be <= 366 for a leap year, date unchanged");
  324. return;
  325. }
  326.  
  327. // otherwise, the date number is valid, just find where in the year it lies
  328. else {
  329. setMonth(1);
  330. setDay(1);
  331. setYear(year);
  332.  
  333. // advance the date from 1/1 by N-1
  334. laterDate(dateNum-1);
  335. }
  336. }
  337.  
  338. /**
  339. * Advances the date by one day (back compatibility wrapper)
  340. */
  341. public void nextDay() {
  342. // provides back compatibility with the former SimpleDate
  343. nextDate();
  344. }
  345.  
  346. /**
  347. * Advances the date by one day (uses consistent naming scheme)
  348. */
  349. public void nextDate() {
  350. // same as nextDay(), uses a consistent naming scheme ("...Date")
  351. laterDate(1);
  352. }
  353.  
  354. /**
  355. * Advances the date by the desired number of days.
  356. * If numDays &lt; 0, the date will REGRESS.
  357. * @param numDays number of data to advance (numDays &ge; 0)
  358. */
  359. public void laterDate(int numDays) {
  360.  
  361. // counter
  362. int temp = 1;
  363.  
  364. if (numDays < 0) {
  365. priorDate(-numDays);
  366. }
  367. else {
  368. while (temp <= numDays) {
  369. day++;
  370. temp++;
  371.  
  372. // if date is invalid, day is too big, update month
  373. if (!isValidDate(month, day, year)) {
  374. day = 1;
  375. month++;
  376. }
  377.  
  378. // if date is still invalid, month is too big, update month/year
  379. if (!isValidDate(month, day, year)) {
  380. month = 1;
  381. year++;
  382. }
  383.  
  384. } // end while
  385. } // end else
  386. } // end method
  387.  
  388. /**
  389. * Regresses the date by the desired number of days.
  390. * If numDays &lt; 0, the date will ADVANCE.
  391. * @param numDays number of data to regress (numDays &ge; 0)
  392. */
  393. public void priorDate(int numDays) {
  394.  
  395. // counter
  396. int temp = 1;
  397.  
  398. if (numDays < 0) {
  399. laterDate(-numDays);
  400. }
  401.  
  402. else {
  403. while (temp <= numDays) {
  404. day--;
  405. temp++;
  406.  
  407. // if date is invalid, day is too small, update month
  408. if (!isValidDate(month, day, year)) {
  409. month--;
  410. day = daysInMonth(month, year);
  411. }
  412.  
  413. // if date is still invalid, month is too small, update month/year
  414. if (!isValidDate(month, day, year)) {
  415. month = 12;
  416. year--;
  417. day = 31;
  418. }
  419.  
  420. } // end while
  421. }
  422. }
  423.  
  424. // equivalence and comparison --------------------------------------
  425.  
  426. /**
  427. * Determines the equality of a CS12Date against another one, or any other object.
  428. * Text fields must also be equal for two objects to be equal.
  429. * @param obj generic object to be compared
  430. * @return equality status
  431. */
  432. public boolean equals(Object obj) {
  433. if (obj instanceof CS12Date) {
  434. // good object, so cast it
  435. CS12Date temp = (CS12Date) obj;
  436.  
  437. // check data field-by-field
  438. if ((this.getYear() == temp.getYear()) &&
  439. (this.getMonth() == temp.getMonth()) &&
  440. (this.getDay() == temp.getDay()) &&
  441. (this.getText().equals(temp.getText())) ) {
  442. return true;
  443. }
  444. else {
  445. return false;
  446. }
  447. }
  448. else {
  449. // object is not a CS12Date, so can't compare
  450. return false;
  451. }
  452. }
  453.  
  454. /**
  455. * Compares two CS12Date objects date-wise. <br>
  456. * If result = 0, the two dates are the same <br>
  457. * If result &gt; 0, date2 is later in time than current date <br>
  458. * If result &lt; 0, date2 is earlier in time than the current date
  459. * @param date2 the CS12Date which is to be compared
  460. * @return comparison result
  461. */
  462. public int compare(CS12Date date2) {
  463.  
  464. int result;
  465. int y1 = this.year;
  466. int y2 = date2.getYear();
  467. int m1 = this.month;
  468. int m2 = date2.getMonth();
  469. int d1 = this.day;
  470. int d2 = date2.getDay();
  471.  
  472. // all fields are the same: dates are identical
  473. if ((y1 == y2) && (m1 == m2) && (d1 == d2)) {
  474. result = 0;
  475. }
  476.  
  477. // years differ
  478. else if (y1 < y2) {
  479. result = 1;
  480. }
  481. else if (y1 > y2) {
  482. result = -1;
  483. }
  484.  
  485. // months differ
  486. else if (m1 < m2) {
  487. result = 1;
  488. }
  489. else if (m1 > m2) {
  490. result = -1;
  491. }
  492.  
  493. // days differ
  494. else if (d1 < d2) {
  495. result = 1;
  496. }
  497. else {
  498. result = -1;
  499. }
  500.  
  501. return result;
  502. }
  503.  
  504. // private utility methods -----------------------------------------
  505.  
  506. /**
  507. * Checks T/F whether provided data parameters constitute a valid date.
  508. * Intended for private internal use of this class.
  509. * @param mm Month parameter to be checked
  510. * @param dd Day parameter to be checked
  511. * @param yyyy Year parameter to be checked
  512. * @return validity status of the date
  513. */
  514. private boolean isValidDate(int mm, int dd, int yyyy) {
  515.  
  516. // first check for arguments validity
  517. if ((mm < 1) || (mm > 12)) {
  518. return false;
  519. }
  520. else if (yyyy < 1) {
  521. return false;
  522. }
  523. else if ((dd < 1) || (dd > daysInMonth(mm, yyyy))) {
  524. return false;
  525. }
  526. else {
  527. return true;
  528. }
  529. }
  530.  
  531. /**
  532. * Checks whether the year is a leap year
  533. * @param yyyy Year to be checked
  534. * @return flag telling whether the year is a leap year
  535. */
  536. private boolean isLeapYear(int yyyy) {
  537. if ((yyyy % 4) > 0) {
  538. // definitely not a leap year
  539. return false;
  540. }
  541. else if ( ((yyyy % 100) == 0) && ((yyyy % 400) > 0) ) {
  542. // simple divisible by 100 is not enough,
  543. // 1800 and 1900 are NOT leap years
  544. return false;
  545. }
  546. else {
  547. return true;
  548. }
  549. }
  550.  
  551. /**
  552. * Returns the number of days in a given month of a given year.
  553. * @param mm Month to be checked
  554. * @param yyyy Year to be checked
  555. * @return numDays Number of days in the given month/year
  556. */
  557. private int daysInMonth(int mm, int yyyy) {
  558. int numDays;
  559.  
  560. // determine days in a given month
  561. switch (mm) {
  562. // "... all the rest have 31"
  563. case 1:
  564. case 3:
  565. case 5:
  566. case 7:
  567. case 8:
  568. case 10:
  569. case 12:
  570. numDays = 31;
  571. break;
  572.  
  573. // "30 days hath September, April, June, and November..."
  574. case 4:
  575. case 6:
  576. case 9:
  577. case 11:
  578. numDays = 30;
  579. break;
  580.  
  581. // February
  582. case 2:
  583. numDays = (isLeapYear(yyyy) ? 29 : 28);
  584. break;
  585.  
  586. default:
  587. // should never get here for this internal method
  588. numDays = 0;
  589. break;
  590. }
  591. return numDays;
  592. }
  593.  
  594. /**
  595. * Prints a user-defined spacer line to stdout.
  596. * Intended for private internal use of this class.
  597. * @param ch character to be used for the spacer
  598. * @param num width of the spacer, in characters
  599. */
  600. private void spacer(char ch, int num) {
  601. for (int i=0; i<num; i++) {
  602. System.out.print(ch);
  603. }
  604. System.out.println();
  605. }
  606.  
  607. /**
  608. * Prints a default spacer ('=' x40) to stdout.
  609. * Intended for private internal use of this class.
  610. */
  611. private void spacer() {
  612. final char SEP_CHAR = '='; // default separator character
  613. final int SEP_NUM = 40; // default separator width
  614.  
  615. spacer(SEP_CHAR, SEP_NUM);
  616. }
  617.  
  618. /**
  619. * Prints a user-supplied message in a standard error format.
  620. * Intended for private internal use of this class.
  621. * @param message error message to be displayed
  622. */
  623. private void error(String message) {
  624. System.out.println("ERROR: " + message);
  625. }
  626.  
  627. } // end class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement