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 static com.healthmarketscience.jackcess.Database.*;
35 import static com.healthmarketscience.jackcess.DatabaseBuilder.*;
36 import static com.healthmarketscience.jackcess.TestUtil.*;
37 import com.healthmarketscience.jackcess.impl.ColumnImpl;
38 import com.healthmarketscience.jackcess.impl.DatabaseImpl;
39 import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
40 import static org.junit.jupiter.api.Assertions.*;
41 import org.junit.jupiter.api.Test;
42
43
44
45
46
47 public class LocalDateTimeTest
48 {
49
50 @Test
51 public void testWriteAndReadLocalDate() throws Exception {
52 for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
53 try (Database db = createMem(fileFormat)) {
54
55 db.setDateTimeType(DateTimeType.LOCAL_DATE_TIME);
56
57 Table table = newTable("test")
58 .addColumn(newColumn("name", DataType.TEXT))
59 .addColumn(newColumn("date", DataType.SHORT_DATE_TIME))
60 .toTable(db);
61
62
63
64 long curTimeNoMillis = (System.currentTimeMillis() / 1000L);
65 curTimeNoMillis *= 1000L;
66
67 DateFormat df = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
68 List<Date> dates =
69 new ArrayList<Date>(
70 Arrays.asList(
71 df.parse("19801231 00:00:00"),
72 df.parse("19930513 14:43:27"),
73 null,
74 df.parse("20210102 02:37:00"),
75 new Date(curTimeNoMillis)));
76
77 Calendar c = Calendar.getInstance();
78 for(int year = 1801; year < 2050; year +=3) {
79 for(int month = 0; month <= 12; ++month) {
80 for(int day = 1; day < 29; day += 3) {
81 c.clear();
82 c.set(Calendar.YEAR, year);
83 c.set(Calendar.MONTH, month);
84 c.set(Calendar.DAY_OF_MONTH, day);
85 dates.add(c.getTime());
86 }
87 }
88 }
89
90 ((DatabaseImpl)db).getPageChannel().startWrite();
91 try {
92 for(Date d : dates) {
93 table.addRow("row " + d, d);
94 }
95 } finally {
96 ((DatabaseImpl)db).getPageChannel().finishWrite();
97 }
98
99 List<LocalDateTime> foundDates = new ArrayList<LocalDateTime>();
100 for(Row row : table) {
101 foundDates.add(row.getLocalDateTime("date"));
102 }
103
104 assertEquals(dates.size(), foundDates.size());
105 for(int i = 0; i < dates.size(); ++i) {
106 Date expected = dates.get(i);
107 LocalDateTime found = foundDates.get(i);
108 assertSameDate(expected, found);
109 }
110
111 }
112 }
113 }
114
115 @Test
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 try (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 }
147 }
148
149 for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.OLD_DATES)) {
150 try (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 }
163 }
164
165 }
166
167 @Test
168 public void testZoneId() throws Exception
169 {
170 ZoneId zoneId = ZoneId.of("America/New_York");
171 doTestZoneId(zoneId);
172
173 zoneId = ZoneId.of("Australia/Sydney");
174 doTestZoneId(zoneId);
175 }
176
177 private static void doTestZoneId(final ZoneId zoneId) throws Exception
178 {
179 final TimeZone tz = TimeZone.getTimeZone(zoneId);
180 ColumnImpl col = new ColumnImpl(null, null, DataType.SHORT_DATE_TIME, 0, 0, 0) {
181 @Override
182 public TimeZone getTimeZone() { return tz; }
183 @Override
184 public ZoneId getZoneId() { return zoneId; }
185 @Override
186 public ColumnImpl.DateTimeFactory getDateTimeFactory() {
187 return getDateTimeFactory(DateTimeType.LOCAL_DATE_TIME);
188 }
189 };
190
191 SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd");
192 df.setTimeZone(tz);
193
194 long startDate = df.parse("2012.01.01").getTime();
195 long endDate = df.parse("2013.01.01").getTime();
196
197 Calendar curCal = Calendar.getInstance(tz);
198 curCal.setTimeInMillis(startDate);
199
200 DateTimeFormatter sdf = DateTimeFormatter.ofPattern("uuuu.MM.dd HH:mm:ss");
201
202 while(curCal.getTimeInMillis() < endDate) {
203 Date curDate = curCal.getTime();
204 LocalDateTime curLdt = LocalDateTime.ofInstant(
205 Instant.ofEpochMilli(curDate.getTime()), zoneId);
206 LocalDateTime newLdt = ColumnImpl.ldtFromLocalDateDouble(
207 col.toDateDouble(curDate));
208 if(!curLdt.equals(newLdt)) {
209 System.out.println("FOO " + curLdt + " " + newLdt);
210 assertEquals(sdf.format(curLdt), sdf.format(newLdt));
211 }
212 curCal.add(Calendar.MINUTE, 30);
213 }
214 }
215
216 @Test
217 public void testWriteAndReadTemporals() throws Exception {
218 ZoneId zoneId = ZoneId.of("America/New_York");
219 for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
220 try (Database db = createMem(fileFormat)) {
221 db.setZoneId(zoneId);
222 db.setDateTimeType(DateTimeType.LOCAL_DATE_TIME);
223
224 Table table = newTable("test")
225 .addColumn(newColumn("name", DataType.TEXT))
226 .addColumn(newColumn("date", DataType.SHORT_DATE_TIME))
227 .toTable(db);
228
229
230
231 long curTimeNoMillis = (System.currentTimeMillis() / 1000L);
232 curTimeNoMillis *= 1000L;
233
234 DateFormat df = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
235 List<Date> tmpDates =
236 new ArrayList<Date>(
237 Arrays.asList(
238 df.parse("19801231 00:00:00"),
239 df.parse("19930513 14:43:27"),
240 df.parse("20210102 02:37:00"),
241 new Date(curTimeNoMillis)));
242
243 List<Object> objs = new ArrayList<Object>();
244 List<LocalDateTime> expected = new ArrayList<LocalDateTime>();
245 for(Date d : tmpDates) {
246 Instant inst = Instant.ofEpochMilli(d.getTime());
247 objs.add(inst);
248 ZonedDateTime zdt = inst.atZone(zoneId);
249 objs.add(zdt);
250 LocalDateTime ldt = zdt.toLocalDateTime();
251 objs.add(ldt);
252
253 for(int i = 0; i < 3; ++i) {
254 expected.add(ldt);
255 }
256 }
257
258 ((DatabaseImpl)db).getPageChannel().startWrite();
259 try {
260 for(Object o : objs) {
261 table.addRow("row " + o, o);
262 }
263 } finally {
264 ((DatabaseImpl)db).getPageChannel().finishWrite();
265 }
266
267 List<LocalDateTime> foundDates = new ArrayList<LocalDateTime>();
268 for(Row row : table) {
269 foundDates.add(row.getLocalDateTime("date"));
270 }
271
272 assertEquals(expected, foundDates);
273
274 }
275 }
276 }
277
278 }