You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TestHSSFDateUtil.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hssf.usermodel;
  16. import static org.junit.Assert.assertEquals;
  17. import static org.junit.Assert.assertFalse;
  18. import static org.junit.Assert.assertTrue;
  19. import java.io.IOException;
  20. import java.text.ParseException;
  21. import java.text.SimpleDateFormat;
  22. import java.util.Calendar;
  23. import java.util.Date;
  24. import java.util.GregorianCalendar;
  25. import java.util.TimeZone;
  26. import org.apache.poi.hssf.HSSFTestDataSamples;
  27. import org.apache.poi.hssf.model.InternalWorkbook;
  28. import org.apache.poi.ss.usermodel.DateUtil;
  29. import org.junit.Test;
  30. /**
  31. * Class TestHSSFDateUtil
  32. *
  33. *
  34. * @author Dan Sherman (dsherman at isisph.com)
  35. * @author Hack Kampbjorn (hak at 2mba.dk)
  36. * @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
  37. * @author Alex Jacoby (ajacoby at gmail.com)
  38. * @version %I%, %G%
  39. */
  40. public final class TestHSSFDateUtil {
  41. public static final int CALENDAR_JANUARY = 0;
  42. public static final int CALENDAR_FEBRUARY = 1;
  43. public static final int CALENDAR_MARCH = 2;
  44. public static final int CALENDAR_APRIL = 3;
  45. public static final int CALENDAR_JULY = 6;
  46. public static final int CALENDAR_OCTOBER = 9;
  47. /**
  48. * Checks the date conversion functions in the HSSFDateUtil class.
  49. */
  50. @Test
  51. public void dateConversion() {
  52. // Iteratating over the hours exposes any rounding issues.
  53. for (int hour = 0; hour < 23; hour++)
  54. {
  55. GregorianCalendar date = new GregorianCalendar(2002, 0, 1,
  56. hour, 1, 1);
  57. double excelDate =
  58. HSSFDateUtil.getExcelDate(date.getTime(), false);
  59. assertEquals("Checking hour = " + hour, date.getTime().getTime(),
  60. HSSFDateUtil.getJavaDate(excelDate, false).getTime());
  61. }
  62. // check 1900 and 1904 date windowing conversions
  63. double excelDate = 36526.0;
  64. // with 1900 windowing, excelDate is Jan. 1, 2000
  65. // with 1904 windowing, excelDate is Jan. 2, 2004
  66. GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000
  67. Date dateIf1900 = cal.getTime();
  68. cal.add(GregorianCalendar.YEAR,4); // now Jan. 1, 2004
  69. cal.add(GregorianCalendar.DATE,1); // now Jan. 2, 2004
  70. Date dateIf1904 = cal.getTime();
  71. // 1900 windowing
  72. assertEquals("Checking 1900 Date Windowing",
  73. dateIf1900.getTime(),
  74. HSSFDateUtil.getJavaDate(excelDate,false).getTime());
  75. // 1904 windowing
  76. assertEquals("Checking 1904 Date Windowing",
  77. dateIf1904.getTime(),
  78. HSSFDateUtil.getJavaDate(excelDate,true).getTime());
  79. }
  80. /**
  81. * Checks the conversion of a java.util.date to Excel on a day when
  82. * Daylight Saving Time starts.
  83. */
  84. @Test
  85. public void excelConversionOnDSTStart() {
  86. TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
  87. TimeZone.setDefault(cet);
  88. Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
  89. for (int hour = 0; hour < 24; hour++) {
  90. // Skip 02:00 CET as that is the Daylight change time
  91. // and Java converts it automatically to 03:00 CEST
  92. if (hour == 2) {
  93. continue;
  94. }
  95. cal.set(Calendar.HOUR_OF_DAY, hour);
  96. Date javaDate = cal.getTime();
  97. double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
  98. double difference = excelDate - Math.floor(excelDate);
  99. int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
  100. assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
  101. hour,
  102. differenceInHours);
  103. assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
  104. javaDate.getTime(),
  105. HSSFDateUtil.getJavaDate(excelDate, false).getTime());
  106. }
  107. }
  108. /**
  109. * Checks the conversion of an Excel date to a java.util.date on a day when
  110. * Daylight Saving Time starts.
  111. */
  112. @Test
  113. public void javaConversionOnDSTStart() {
  114. TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
  115. TimeZone.setDefault(cet);
  116. Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
  117. double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
  118. double oneHour = 1.0 / 24;
  119. double oneMinute = oneHour / 60;
  120. for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
  121. // Skip 02:00 CET as that is the Daylight change time
  122. // and Java converts it automatically to 03:00 CEST
  123. if (hour == 2) {
  124. continue;
  125. }
  126. cal.set(Calendar.HOUR_OF_DAY, hour);
  127. Date javaDate = HSSFDateUtil.getJavaDate(excelDate, false);
  128. assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
  129. excelDate,
  130. HSSFDateUtil.getExcelDate(javaDate, false), oneMinute);
  131. }
  132. }
  133. /**
  134. * Checks the conversion of a java.util.Date to Excel on a day when
  135. * Daylight Saving Time ends.
  136. */
  137. @Test
  138. public void excelConversionOnDSTEnd() {
  139. TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
  140. TimeZone.setDefault(cet);
  141. Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
  142. for (int hour = 0; hour < 24; hour++) {
  143. cal.set(Calendar.HOUR_OF_DAY, hour);
  144. Date javaDate = cal.getTime();
  145. double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
  146. double difference = excelDate - Math.floor(excelDate);
  147. int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
  148. assertEquals("Checking " + hour + " hour on Daylight Saving Time end date",
  149. hour,
  150. differenceInHours);
  151. assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
  152. javaDate.getTime(),
  153. HSSFDateUtil.getJavaDate(excelDate, false).getTime());
  154. }
  155. }
  156. /**
  157. * Checks the conversion of an Excel date to java.util.Date on a day when
  158. * Daylight Saving Time ends.
  159. */
  160. @Test
  161. public void javaConversionOnDSTEnd() {
  162. TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
  163. TimeZone.setDefault(cet);
  164. Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
  165. double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
  166. double oneHour = 1.0 / 24;
  167. double oneMinute = oneHour / 60;
  168. for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
  169. cal.set(Calendar.HOUR_OF_DAY, hour);
  170. Date javaDate = HSSFDateUtil.getJavaDate(excelDate, false);
  171. assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
  172. excelDate,
  173. HSSFDateUtil.getExcelDate(javaDate, false), oneMinute);
  174. }
  175. }
  176. /**
  177. * Tests that we deal with time-zones properly
  178. */
  179. @Test
  180. public void calendarConversion() {
  181. GregorianCalendar date = new GregorianCalendar(2002, 0, 1, 12, 1, 1);
  182. Date expected = date.getTime();
  183. // Iterating over the hours exposes any rounding issues.
  184. for (int hour = -12; hour <= 12; hour++)
  185. {
  186. String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00";
  187. date.setTimeZone(TimeZone.getTimeZone(id));
  188. date.set(Calendar.HOUR_OF_DAY, 12);
  189. double excelDate = HSSFDateUtil.getExcelDate(date, false);
  190. Date javaDate = HSSFDateUtil.getJavaDate(excelDate);
  191. // Should match despite time-zone
  192. assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime());
  193. }
  194. // Check that the timezone aware getter works correctly
  195. TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
  196. TimeZone ldn = TimeZone.getTimeZone("Europe/London");
  197. TimeZone.setDefault(cet);
  198. // 12:45 on 27th April 2012
  199. double excelDate = 41026.53125;
  200. // Same, no change
  201. assertEquals(
  202. HSSFDateUtil.getJavaDate(excelDate, false).getTime(),
  203. HSSFDateUtil.getJavaDate(excelDate, false, cet).getTime()
  204. );
  205. // London vs Copenhagen, should differ by an hour
  206. Date cetDate = HSSFDateUtil.getJavaDate(excelDate, false);
  207. Date ldnDate = HSSFDateUtil.getJavaDate(excelDate, false, ldn);
  208. assertEquals(ldnDate.getTime() - cetDate.getTime(), 60*60*1000);
  209. }
  210. /**
  211. * Tests that we correctly detect date formats as such
  212. */
  213. @Test
  214. public void identifyDateFormats() {
  215. // First up, try with a few built in date formats
  216. short[] builtins = new short[] { 0x0e, 0x0f, 0x10, 0x16, 0x2d, 0x2e };
  217. for(int i=0; i<builtins.length; i++) {
  218. String formatStr = HSSFDataFormat.getBuiltinFormat(builtins[i]);
  219. assertTrue( HSSFDateUtil.isInternalDateFormat(builtins[i]) );
  220. assertTrue( HSSFDateUtil.isADateFormat(builtins[i],formatStr) );
  221. }
  222. // Now try a few built-in non date formats
  223. builtins = new short[] { 0x01, 0x02, 0x17, 0x1f, 0x30 };
  224. for(int i=0; i<builtins.length; i++) {
  225. String formatStr = HSSFDataFormat.getBuiltinFormat(builtins[i]);
  226. assertFalse( HSSFDateUtil.isInternalDateFormat(builtins[i]) );
  227. assertFalse( HSSFDateUtil.isADateFormat(builtins[i],formatStr) );
  228. }
  229. // Now for some non-internal ones
  230. // These come after the real ones
  231. int numBuiltins = HSSFDataFormat.getNumberOfBuiltinBuiltinFormats();
  232. assertTrue(numBuiltins < 60);
  233. short formatId = 60;
  234. assertFalse( HSSFDateUtil.isInternalDateFormat(formatId) );
  235. // Valid ones first
  236. String[] formats = new String[] {
  237. "yyyy-mm-dd", "yyyy/mm/dd", "yy/mm/dd", "yy/mmm/dd",
  238. "dd/mm/yy", "dd/mm/yyyy", "dd/mmm/yy",
  239. "dd-mm-yy", "dd-mm-yyyy",
  240. "DD-MM-YY", "DD-mm-YYYY",
  241. "dd\\-mm\\-yy", // Sometimes escaped
  242. "dd.mm.yyyy", "dd\\.mm\\.yyyy",
  243. "dd\\ mm\\.yyyy AM", "dd\\ mm\\.yyyy pm",
  244. "dd\\ mm\\.yyyy\\-dd", "[h]:mm:ss",
  245. "mm/dd/yy", "\"mm\"/\"dd\"/\"yy\"",
  246. "m\\/d\\/yyyy",
  247. // These crazy ones are valid
  248. "yyyy-mm-dd;@", "yyyy/mm/dd;@",
  249. "dd-mm-yy;@", "dd-mm-yyyy;@",
  250. // These even crazier ones are also valid
  251. // (who knows what they mean though...)
  252. "[$-F800]dddd\\,\\ mmm\\ dd\\,\\ yyyy",
  253. "[$-F900]ddd/mm/yyy",
  254. // These ones specify colours, who knew that was allowed?
  255. "[BLACK]dddd/mm/yy",
  256. "[yeLLow]yyyy-mm-dd"
  257. };
  258. for(int i=0; i<formats.length; i++) {
  259. assertTrue(
  260. formats[i] + " is a date format",
  261. HSSFDateUtil.isADateFormat(formatId, formats[i])
  262. );
  263. }
  264. // Then time based ones too
  265. formats = new String[] {
  266. "yyyy-mm-dd hh:mm:ss", "yyyy/mm/dd HH:MM:SS",
  267. "mm/dd HH:MM", "yy/mmm/dd SS",
  268. "mm/dd HH:MM AM", "mm/dd HH:MM am",
  269. "mm/dd HH:MM PM", "mm/dd HH:MM pm",
  270. "m/d/yy h:mm AM/PM",
  271. "hh:mm:ss", "hh:mm:ss.0", "mm:ss.0",
  272. //support elapsed time [h],[m],[s]
  273. "[hh]", "[mm]", "[ss]", "[SS]", "[red][hh]"
  274. };
  275. for(int i=0; i<formats.length; i++) {
  276. assertTrue(
  277. formats[i] + " is a datetime format",
  278. HSSFDateUtil.isADateFormat(formatId, formats[i])
  279. );
  280. }
  281. // Then invalid ones
  282. formats = new String[] {
  283. "yyyy*mm*dd",
  284. "0.0", "0.000",
  285. "0%", "0.0%",
  286. "[]Foo", "[BLACK]0.00%",
  287. "[ms]", "[Mh]",
  288. "", null
  289. };
  290. for(int i=0; i<formats.length; i++) {
  291. assertFalse(
  292. formats[i] + " is not a date or datetime format",
  293. HSSFDateUtil.isADateFormat(formatId, formats[i])
  294. );
  295. }
  296. // And these are ones we probably shouldn't allow,
  297. // but would need a better regexp
  298. formats = new String[] {
  299. "yyyy:mm:dd",
  300. };
  301. for(int i=0; i<formats.length; i++) {
  302. // assertFalse( HSSFDateUtil.isADateFormat(formatId, formats[i]) );
  303. }
  304. }
  305. /**
  306. * Test that against a real, test file, we still do everything
  307. * correctly
  308. * @throws IOException
  309. */
  310. @Test
  311. public void onARealFile() throws IOException {
  312. HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("DateFormats.xls");
  313. HSSFSheet sheet = workbook.getSheetAt(0);
  314. InternalWorkbook wb = workbook.getWorkbook();
  315. HSSFRow row;
  316. HSSFCell cell;
  317. HSSFCellStyle style;
  318. double aug_10_2007 = 39304.0;
  319. // Should have dates in 2nd column
  320. // All of them are the 10th of August
  321. // 2 US dates, 3 UK dates
  322. row = sheet.getRow(0);
  323. cell = row.getCell(1);
  324. style = cell.getCellStyle();
  325. assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
  326. assertEquals("d-mmm-yy", style.getDataFormatString());
  327. assertTrue(HSSFDateUtil.isInternalDateFormat(style.getDataFormat()));
  328. assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
  329. assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
  330. row = sheet.getRow(1);
  331. cell = row.getCell(1);
  332. style = cell.getCellStyle();
  333. assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
  334. assertFalse(HSSFDateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
  335. assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
  336. assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
  337. row = sheet.getRow(2);
  338. cell = row.getCell(1);
  339. style = cell.getCellStyle();
  340. assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
  341. assertTrue(HSSFDateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
  342. assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
  343. assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
  344. row = sheet.getRow(3);
  345. cell = row.getCell(1);
  346. style = cell.getCellStyle();
  347. assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
  348. assertFalse(HSSFDateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
  349. assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
  350. assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
  351. row = sheet.getRow(4);
  352. cell = row.getCell(1);
  353. style = cell.getCellStyle();
  354. assertEquals(aug_10_2007, cell.getNumericCellValue(), 0.0001);
  355. assertFalse(HSSFDateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat()));
  356. assertTrue(HSSFDateUtil.isADateFormat(style.getDataFormat(), style.getDataFormatString()));
  357. assertTrue(HSSFDateUtil.isCellDateFormatted(cell));
  358. workbook.close();
  359. }
  360. @Test
  361. public void excelDateBorderCases() throws ParseException {
  362. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
  363. assertEquals(1.0, DateUtil.getExcelDate(df.parse("1900-01-01")), 0.00001);
  364. assertEquals(31.0, DateUtil.getExcelDate(df.parse("1900-01-31")), 0.00001);
  365. assertEquals(32.0, DateUtil.getExcelDate(df.parse("1900-02-01")), 0.00001);
  366. assertEquals(/* BAD_DATE! */ -1.0, DateUtil.getExcelDate(df.parse("1899-12-31")), 0.00001);
  367. }
  368. @Test
  369. public void dateBug_2Excel() {
  370. assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_FEBRUARY, 28), false), 0.00001);
  371. assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_MARCH, 1), false), 0.00001);
  372. assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_FEBRUARY, 28), false), 0.00001);
  373. assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_MARCH, 1), false), 0.00001);
  374. assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_JANUARY, 1), false), 0.00001);
  375. assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, CALENDAR_MARCH, 28), false), 0.00001);
  376. }
  377. @Test
  378. public void dateBug_2Java() {
  379. assertEquals(createDate(1900, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0, false));
  380. assertEquals(createDate(1900, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(61.0, false));
  381. assertEquals(createDate(2002, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00, false));
  382. assertEquals(createDate(2002, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(37316.00, false));
  383. assertEquals(createDate(2002, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00, false));
  384. assertEquals(createDate(2004, CALENDAR_MARCH, 28), HSSFDateUtil.getJavaDate(38074.00, false));
  385. }
  386. @Test
  387. public void date1904() {
  388. assertEquals(createDate(1904, CALENDAR_JANUARY, 2), HSSFDateUtil.getJavaDate(1.0, true));
  389. assertEquals(createDate(1904, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(0.0, true));
  390. assertEquals(0.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 1), true), 0.00001);
  391. assertEquals(1.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 2), true), 0.00001);
  392. assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(35981, false));
  393. assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(34519, true));
  394. assertEquals(35981.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), false), 0.00001);
  395. assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), true), 0.00001);
  396. }
  397. /**
  398. * @param month zero based
  399. * @param day one based
  400. */
  401. private static Date createDate(int year, int month, int day) {
  402. return createDate(year, month, day, 0, 0, 0);
  403. }
  404. /**
  405. * @param month zero based
  406. * @param day one based
  407. */
  408. private static Date createDate(int year, int month, int day, int hour, int minute, int second) {
  409. Calendar c = new GregorianCalendar();
  410. c.set(year, month, day, hour, minute, second);
  411. c.set(Calendar.MILLISECOND, 0);
  412. return c.getTime();
  413. }
  414. /**
  415. * Check if HSSFDateUtil.getAbsoluteDay works as advertised.
  416. */
  417. @Test
  418. public void absoluteDay() {
  419. // 1 Jan 1900 is 1 day after 31 Dec 1899
  420. GregorianCalendar calendar = new GregorianCalendar(1900, 0, 1);
  421. assertEquals("Checking absolute day (1 Jan 1900)", 1, HSSFDateUtil.absoluteDay(calendar, false));
  422. // 1 Jan 1901 is 366 days after 31 Dec 1899
  423. calendar = new GregorianCalendar(1901, 0, 1);
  424. assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false));
  425. }
  426. @Test
  427. public void convertTime() {
  428. final double delta = 1E-7; // a couple of digits more accuracy than strictly required
  429. assertEquals(0.5, HSSFDateUtil.convertTime("12:00"), delta);
  430. assertEquals(2.0/3, HSSFDateUtil.convertTime("16:00"), delta);
  431. assertEquals(0.0000116, HSSFDateUtil.convertTime("0:00:01"), delta);
  432. assertEquals(0.7330440, HSSFDateUtil.convertTime("17:35:35"), delta);
  433. }
  434. @Test
  435. public void parseDate() {
  436. assertEquals(createDate(2008, Calendar.AUGUST, 3), HSSFDateUtil.parseYYYYMMDDDate("2008/08/03"));
  437. assertEquals(createDate(1994, Calendar.MAY, 1), HSSFDateUtil.parseYYYYMMDDDate("1994/05/01"));
  438. }
  439. /**
  440. * Ensure that date values *with* a fractional portion get the right time of day
  441. */
  442. @Test
  443. public void convertDateTime() {
  444. // Excel day 30000 is date 18-Feb-1982
  445. // 0.7 corresponds to time 16:48:00
  446. Date actual = HSSFDateUtil.getJavaDate(30000.7);
  447. Date expected = createDate(1982, 1, 18, 16, 48, 0);
  448. assertEquals(expected, actual);
  449. }
  450. /**
  451. * User reported a datetime issue in POI-2.5:
  452. * Setting Cell's value to Jan 1, 1900 without a time doesn't return the same value set to
  453. * @throws IOException
  454. */
  455. @Test
  456. public void bug19172() throws IOException
  457. {
  458. HSSFWorkbook workbook = new HSSFWorkbook();
  459. HSSFSheet sheet = workbook.createSheet();
  460. HSSFCell cell = sheet.createRow(0).createCell(0);
  461. Calendar cal = Calendar.getInstance();
  462. // A pseudo special Excel dates
  463. cal.set(1900, 0, 1);
  464. Date valueToTest = cal.getTime();
  465. cell.setCellValue(valueToTest);
  466. Date returnedValue = cell.getDateCellValue();
  467. assertEquals(valueToTest.getTime(), returnedValue.getTime());
  468. workbook.close();
  469. }
  470. /**
  471. * DateUtil.isCellFormatted(Cell) should not true for a numeric cell
  472. * that's formatted as ".0000"
  473. */
  474. @Test
  475. public void bug54557() throws Exception {
  476. final String format = ".0000";
  477. boolean isDateFormat = HSSFDateUtil.isADateFormat(165, format);
  478. assertEquals(false, isDateFormat);
  479. }
  480. @Test
  481. public void bug56269() throws Exception {
  482. double excelFraction = 41642.45833321759d;
  483. Calendar calNoRound = HSSFDateUtil.getJavaCalendar(excelFraction, false);
  484. assertEquals(10, calNoRound.get(Calendar.HOUR));
  485. assertEquals(59, calNoRound.get(Calendar.MINUTE));
  486. assertEquals(59, calNoRound.get(Calendar.SECOND));
  487. Calendar calRound = HSSFDateUtil.getJavaCalendar(excelFraction, false, null, true);
  488. assertEquals(11, calRound.get(Calendar.HOUR));
  489. assertEquals(0, calRound.get(Calendar.MINUTE));
  490. assertEquals(0, calRound.get(Calendar.SECOND));
  491. }
  492. }