ISO 8601
РЕШЕНО Таким образом, программа зависала из-за того, что мой CSV не соблюдал правильный формат даты и времени (см. Комментарии ниже).
При обмене датой-время значения в виде текста, используйте стандартные форматы ISO 8601 , а не придумывать свои собственные.Они продуманно разработаны для того, чтобы их было легко разобрать на машине и легко прочитать людям в разных культурах.Итак, 2010-05-04T21:57:34
, а не 2010/5/4 21:57:34
.
Классы java.time по умолчанию используют форматы ISO 8601 при разборе / генерации строк.
Типы данных
Дата-время
2-й и 3-й столбцы вашего фида данных представляют одно и то же: дату с временем дня.Первая - это число полных секунд с даты начала отсчета 1970-01-01T00: 00Z (Z
означает UTC).
Так что глупо включать оба.Как упоминалось выше, 3-й столбец имеет плохо выбранный формат.Подход, основанный на 2-ой колонке - использование отсчета от эпохи - также плохой выбор, на мой взгляд, поскольку он не очевиден, ни один человек не может расшифровать его значение, и поэтому он делает ошибки неочевидными, что затрудняет отладку и ведение журнала.
Чтобы разобраться с тем, что у нас есть, секунды от эпохи можно проанализировать как Instant
.Этот класс представляет момент в UTC.
Instant instant = Instant.ofEpochMilli( 1_273_010_254L ) ;
В 3-м столбце указаны дата и время, но не указан индикатор часового пояса или смещения от UTC.Поскольку он соответствует 2-му столбцу при разборе в секундах с первого момента 1970 года в формате UTC, мы знаем, что его значение предназначено для UTC.Пропуск такой информации - плохая практика, например, наличие денежной суммы без указания валюты.
В идеале оба столбца следует заменить строкой в формате ISO 8601, например, 2010-05-04T21:57:34Z
, включая Z
, чтобы указатьUTC.
Если бы нам пришлось анализировать 3-й столбец, не зная, что он предназначен для UTC, мы бы проанализировали как LocalDateTime
, дату с временем дня, но без часового пояса или смещения.Нам нужно определить шаблон форматирования, соответствующий вашему вводу.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu/M/d HH:mm:ss" );
LocalDateTime localDateTime = LocalDateTime.parse( "2010/5/4 21:57:34" , f );
BigDecimal
Ваши десятичные дробные числа должны быть представлены как BigDecimal
объекты для точности.Никогда не используйте double
/ Double
или float
/ Float
там, где вам важна точность.Эти типы используют технологию с плавающей точкой , которая меняет точность на скорость выполнения.Напротив, BigDecimal
медленный, но точный.
Разбор BigDecimal
из строки.
new BigDecimal ( "78.32" )
Apache Commons CSV
Не пишите код, когда хорошопроверенный код уже существует.Существуют библиотеки, уже написанные для чтения CSV / Разделенных табуляцией файлов.
I use Apache Commons CSV за такую работу.Существует несколько вариантов этих форматов, все они обрабатываются этой библиотекой.
Вот пример кода.Сначала определите класс для хранения ваших данных с именем Reading
.
Reading.java
package com.basilbourque.example;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
public class Reading {
private Integer millis;
private Instant instant;
private LocalDateTime localDateTime;
private Integer light;
private BigDecimal temp;
private BigDecimal vcc;
public Reading ( Integer millis , Instant instant , LocalDateTime localDateTime , Integer light , BigDecimal temp , BigDecimal vcc ) {
// TODO: Add checks for null arguments: Objects.requireNonNull( … ).
this.millis = millis;
this.instant = instant;
this.localDateTime = localDateTime;
this.light = light;
this.temp = temp;
this.vcc = vcc;
}
@Override
public String toString ( ) {
return "com.basilbourque.example.Reading{" +
"millis=" + millis +
", instant=" + instant +
", localDateTime=" + localDateTime +
", light=" + light +
", temp=" + temp +
", vcc=" + vcc +
'}';
}
}
Пример файла данных:
millis,stamp,datetime,light,temp,vcc
1000, 1273010254, 2010/5/4 21:57:34, 333, 78.32, 3.54
2000, 1273010255, 2010/5/4 21:57:35, 333, 78.32, 3.92
3000, 1273010256, 2010/5/4 21:57:36, 344, 78.32, 3.95
А теперь вызовите Commons CSV для анализа этих данных, создания экземпляров Reading
объектов и сбораих.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu/M/d HH:mm:ss" );
List < Reading > readings = new ArrayList <>( 3 );
Reader reader = null;
try {
reader = new FileReader( "/Users/basilbourque/data.csv" );
Iterable < CSVRecord > records = CSVFormat.RFC4180.withIgnoreSurroundingSpaces( true ).withHeader().parse( reader );
for ( CSVRecord record : records ) {
// Grab inputs
String millisInput = record.get( "millis" );
String stampInput = record.get( "stamp" );
String datetimeInput = record.get( "datetime" );
String lightInput = record.get( "light" );
String tempInput = record.get( "temp" );
String vccInput = record.get( "vcc" );
// Parse inputs
Integer millis = Integer.valueOf( millisInput );
Instant instant = Instant.ofEpochSecond( Integer.valueOf( stampInput ) );
LocalDateTime localDateTime = LocalDateTime.parse( datetimeInput , f );
Integer light = Integer.valueOf( lightInput );
BigDecimal temp = new BigDecimal( tempInput );
BigDecimal vcc = new BigDecimal( vccInput );
// Construct object
Reading r = new Reading( millis , instant , localDateTime , light , temp , vcc );
// Collect object
readings.add( r );
}
} catch ( FileNotFoundException e ) {
e.printStackTrace();
} catch ( IOException e ) {
e.printStackTrace();
}
System.out.println( readings );
[com.basilbourque.example.Reading {millis = 1000, instant = 2010-05-04T21: 57: 34Z, localDateTime = 2010-05-04T21: 57: 34, light = 333, temp = 78.32, vcc = 3.54}, com.basilbourque.example.Reading {millis = 2000, instant = 2010-05-04T21: 57: 35Z, localDateTime = 2010-05-04T21: 57: 35,light = 333, temp = 78.32, vcc = 3.92}, com.basilbourque.example.Reading {millis = 3000, instant = 2010-05-04T21: 57: 36Z, localDateTime = 2010-05-04T21: 57: 36, light= 344, temp = 78.32, vcc = 3.95}]
По поводу вашего упоминания:
сохранить данные в массиве
Youв вашем коде используется ArrayList
, а не массив.Смотрите Oracle Tutorials для списков и для массивов , чтобы понять разницу.Обычно лучше всего использовать Java Collections framework .Если размер и скорость действительно имеют значение, мы можем выбрать массив.
О java.time
Фреймворк java.time встроен в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
и & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .
Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .
Вы можете обмениваться java.time объектами непосредственно с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
и more .