1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.healthmarketscience.jackcess;
18
19 import java.text.DateFormat;
20 import java.text.SimpleDateFormat;
21 import java.time.Instant;
22 import java.time.LocalDate;
23 import java.time.LocalDateTime;
24 import java.time.ZoneId;
25 import java.time.ZonedDateTime;
26 import java.time.format.DateTimeFormatter;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Calendar;
30 import java.util.Date;
31 import java.util.List;
32 import java.util.TimeZone;
33
34 import com.healthmarketscience.jackcess.impl.ColumnImpl;
35 import com.healthmarketscience.jackcess.impl.DatabaseImpl;
36 import junit.framework.TestCase;
37 import static com.healthmarketscience.jackcess.TestUtil.*;
38 import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
39 import static com.healthmarketscience.jackcess.Database.*;
40 import static com.healthmarketscience.jackcess.DatabaseBuilder.*;
41
42
43
44
45
46 public class LocalDateTimeTest extends TestCase
47 {
48 public LocalDateTimeTest(String name) throws Exception {
49 super(name);
50 }
51
52 public void testWriteAndReadLocalDate() throws Exception {
53 for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
54 Database db = createMem(fileFormat);
55
56 db.setDateTimeType(DateTimeType.LOCAL_DATE_TIME);
57
58 Table table = newTable("test")
59 .addColumn(newColumn("name", DataType.TEXT))
60 .addColumn(newColumn("date", DataType.SHORT_DATE_TIME))
61 .toTable(db);
62
63
64
65 long curTimeNoMillis = (System.currentTimeMillis() / 1000L);
66 curTimeNoMillis *= 1000L;
67
68 DateFormat df = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
69 List<Date> dates =
70 new ArrayList<Date>(
71 Arrays.asList(
72 df.parse("19801231 00:00:00"),
73 df.parse("19930513 14:43:27"),
74 null,
75 df.parse("20210102 02:37:00"),
76 new Date(curTimeNoMillis)));
77
78 Calendar c = Calendar.getInstance();
79 for(int year = 1801; year < 2050; year +=3) {
80 for(int month = 0; month <= 12; ++month) {
81 for(int day = 1; day < 29; day += 3) {
82 c.clear();
83 c.set(Calendar.YEAR, year);
84 c.set(Calendar.MONTH, month);
85 c.set(Calendar.DAY_OF_MONTH, day);
86 dates.add(c.getTime());
87 }
88 }
89 }
90
91 ((DatabaseImpl)db).getPageChannel().startWrite();
92 try {
93 for(Date d : dates) {
94 table.addRow("row " + d, d);
95 }
96 } finally {
97 ((DatabaseImpl)db).getPageChannel().finishWrite();
98 }
99
100 List<LocalDateTime> foundDates = new ArrayList<LocalDateTime>();
101 for(Row row : table) {
102 foundDates.add(row.getLocalDateTime("date"));
103 }
104
105 assertEquals(dates.size(), foundDates.size());
106 for(int i = 0; i < dates.size(); ++i) {
107 Date expected = dates.get(i);
108 LocalDateTime found = foundDates.get(i);
109 assertSameDate(expected, found);
110 }
111
112 db.close();
113 }
114 }
115
116 public void testAncientLocalDates() throws Exception
117 {
118 ZoneId zoneId = ZoneId.of("America/New_York");
119 DateTimeFormatter sdf = DateTimeFormatter.ofPattern("uuuu-MM-dd");
120
121 List<String> dates = Arrays.asList("1582-10-15", "1582-10-14",
122 "1492-01-10", "1392-01-10");
123
124 for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
125 Database db = createMem(fileFormat);
126 db.setZoneId(zoneId);
127 db.setDateTimeType(DateTimeType.LOCAL_DATE_TIME);
128
129 Table table = newTable("test")
130 .addColumn(newColumn("name", DataType.TEXT))
131 .addColumn(newColumn("date", DataType.SHORT_DATE_TIME))
132 .toTable(db);
133
134 for(String dateStr : dates) {
135 LocalDate ld = LocalDate.parse(dateStr, sdf);
136 table.addRow("row " + dateStr, ld);
137 }
138
139 List<String> foundDates = new ArrayList<String>();
140 for(Row row : table) {
141 foundDates.add(sdf.format(row.getLocalDateTime("date")));
142 }
143
144 assertEquals(dates, foundDates);
145
146 db.close();
147 }
148
149 for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.OLD_DATES)) {
150 Database db = openCopy(testDB);
151 db.setDateTimeType(DateTimeType.LOCAL_DATE_TIME);
152
153 Table t = db.getTable("Table1");
154
155 List<String> foundDates = new ArrayList<String>();
156 for(Row row : t) {
157 foundDates.add(sdf.format(row.getLocalDateTime("DateField")));
158 }
159
160 assertEquals(dates, foundDates);
161
162 db.close();
163 }
164
165 }
166
167 public void testZoneId() throws Exception
168 {
169 ZoneId zoneId = ZoneId.of("America/New_York");
170 doTestZoneId(zoneId);
171
172 zoneId = ZoneId.of("Australia/Sydney");
173 doTestZoneId(zoneId);
174 }
175
176 private static void doTestZoneId(final ZoneId zoneId) throws Exception
177 {
178 final TimeZone tz = TimeZone.getTimeZone(zoneId);
179 ColumnImpl col = new ColumnImpl(null, null, DataType.SHORT_DATE_TIME, 0, 0, 0) {
180 @Override
181 public TimeZone getTimeZone() { return tz; }
182 @Override
183 public ZoneId getZoneId() { return zoneId; }
184 @Override
185 public ColumnImpl.DateTimeFactory getDateTimeFactory() {
186 return getDateTimeFactory(DateTimeType.LOCAL_DATE_TIME);
187 }
188 };
189
190 SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd");
191 df.setTimeZone(tz);
192
193 long startDate = df.parse("2012.01.01").getTime();
194 long endDate = df.parse("2013.01.01").getTime();
195
196 Calendar curCal = Calendar.getInstance(tz);
197 curCal.setTimeInMillis(startDate);
198
199 DateTimeFormatter sdf = DateTimeFormatter.ofPattern("uuuu.MM.dd HH:mm:ss");
200
201 while(curCal.getTimeInMillis() < endDate) {
202 Date curDate = curCal.getTime();
203 LocalDateTime curLdt = LocalDateTime.ofInstant(
204 Instant.ofEpochMilli(curDate.getTime()), zoneId);
205 LocalDateTime newLdt = ColumnImpl.ldtFromLocalDateDouble(
206 col.toDateDouble(curDate));
207 if(!curLdt.equals(newLdt)) {
208 System.out.println("FOO " + curLdt + " " + newLdt);
209 assertEquals(sdf.format(curLdt), sdf.format(newLdt));
210 }
211 curCal.add(Calendar.MINUTE, 30);
212 }
213 }
214
215 public void testWriteAndReadTemporals() throws Exception {
216 ZoneId zoneId = ZoneId.of("America/New_York");
217 for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
218 Database db = createMem(fileFormat);
219 db.setZoneId(zoneId);
220 db.setDateTimeType(DateTimeType.LOCAL_DATE_TIME);
221
222 Table table = newTable("test")
223 .addColumn(newColumn("name", DataType.TEXT))
224 .addColumn(newColumn("date", DataType.SHORT_DATE_TIME))
225 .toTable(db);
226
227
228
229 long curTimeNoMillis = (System.currentTimeMillis() / 1000L);
230 curTimeNoMillis *= 1000L;
231
232 DateFormat df = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
233 List<Date> tmpDates =
234 new ArrayList<Date>(
235 Arrays.asList(
236 df.parse("19801231 00:00:00"),
237 df.parse("19930513 14:43:27"),
238 df.parse("20210102 02:37:00"),
239 new Date(curTimeNoMillis)));
240
241 List<Object> objs = new ArrayList<Object>();
242 List<LocalDateTime> expected = new ArrayList<LocalDateTime>();
243 for(Date d : tmpDates) {
244 Instant inst = Instant.ofEpochMilli(d.getTime());
245 objs.add(inst);
246 ZonedDateTime zdt = inst.atZone(zoneId);
247 objs.add(zdt);
248 LocalDateTime ldt = zdt.toLocalDateTime();
249 objs.add(ldt);
250
251 for(int i = 0; i < 3; ++i) {
252 expected.add(ldt);
253 }
254 }
255
256 ((DatabaseImpl)db).getPageChannel().startWrite();
257 try {
258 for(Object o : objs) {
259 table.addRow("row " + o, o);
260 }
261 } finally {
262 ((DatabaseImpl)db).getPageChannel().finishWrite();
263 }
264
265 List<LocalDateTime> foundDates = new ArrayList<LocalDateTime>();
266 for(Row row : table) {
267 foundDates.add(row.getLocalDateTime("date"));
268 }
269
270 assertEquals(expected, foundDates);
271
272 db.close();
273 }
274 }
275
276 }