Как разобрать OffsetDateTime из файла CSV

Я пытаюсь использовать opencsv для анализа файла csv следующим образом:

2020-09-18 06:50:00.000000

Я пытаюсь добавить проанализированные данные, следуя этому руководству: https://attacomsian.com/blog/spring-boot-upload-parse-csv-file. Это моя модель:

public class MyIndPrd implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @CsvBindByName
    private String service;
    @CsvBindByName
    private OffsetDateTime time;
    @CsvBindByName
    private Long nbAppels;
    @CsvBindByName
    private Double tempsDeReponseMoyenMillisecondes;
    @CsvBindByName
    private Long volume;
    @CsvBindByName
    private Double tempsDeReponseMoyenSecondes;
}

Я пытаюсь разобрать offsetDateTime

при выполнении:

OffsetDateTime odt = OffsetDateTime.parse (myIndPrds.get (i).getTime ());

перед записью

но не похоже, что ты хочешь это делать

@PostMapping("/upload-csv-file")
    public String uplaodCSVFile(@RequestParam("file") MultipartFile file, Model model){
        if (file.isEmpty()){
            model.addAttribute("message", "Veuillez selectionner un fichier csv à importer.");
            model.addAttribute("status", false);
        }else try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {

            // create csv bean reader
            CsvToBean<MyIndPrd> csvToBean = new CsvToBeanBuilder(reader)
                    .withType(MyIndPrd.class)
                    .withSeparator(';')
                    .withIgnoreLeadingWhiteSpace(true)
                    .build();

            // convert CsvToBean object
            List<MyIndPrd> myIndPrds = csvToBean.parse();
            for (int i = 0;i<myIndPrds.size();i++){

                OffsetDateTime odt = OffsetDateTime.parse(myIndPrds.get(i).getTime());

                MyIndPrd ind = new MyIndPrd();
                ind.setService(myIndPrds.get(i).getService());
                ind.setTime(odt);
                ind.setNbAppels(Long.valueOf(myIndPrds.get(i).getNbAppels()));
                ind.setVolume(Long.valueOf(myIndPrds.get(i).getVolume()));
                ind.setTempsDeReponseMoyenMillisecondes(Double.valueOf(myIndPrds.get(i).getTempsDeReponseMoyenMillisecondes()));
                ind.setTempsDeReponseMoyenSecondes(Double.valueOf(myIndPrds.get(i).getTempsDeReponseMoyenSecondes()));
                iMyIndPrdService.saveMyData(ind);
            }


            model.addAttribute("myIndProdCsv", myIndPrds);
            model.addAttribute("status", true);


        } catch (Exception ex) {
            model.addAttribute("message", "An error occurred while processing the CSV file.");
            model.addAttribute("status", false);
        }
        return "mon-dasboard";
    }

Спасибо за вашу помощь

1 ответ

Решение

Строка даты и времени (например, 2020-09-18 06:50:00.000000 как вы упомянули в вопросе) в CSV нет смещения часового пояса, и поэтому наиболее подходящим типом для его анализа будет LocalDateTime.

Вы можете определить класс конвертера для преобразования строки даты и времени из CSV в LocalDateTime.

public class LocalDateTimeConverter extends AbstractBeanField {
    @Override
    protected Object convert(String s) throws CsvDataTypeMismatchException, CsvConstraintViolationException {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.n");
        LocalDateTime ldt = LocalDateTime.parse(strDate, dtf);
        return ldt;
    }
}

а затем вы можете аннотировать поле как

@CsvBindByName(converter = LocalDateTimeConverter.class)
private LocalDateTime time;

Однако, если вы все еще хотите проанализировать строку даты и времени в OffsetDateTime, вот как это сделать:

public class OffsetDateTimeConverter extends AbstractBeanField {
    @Override
    protected Object convert(String s) throws CsvDataTypeMismatchException, CsvConstraintViolationException {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.n").withZone(ZoneId.systemDefault());
        ZonedDateTime zdt = ZonedDateTime.parse(strDate, dtf);
        OffsetDateTime odt = zdt.toOffsetDateTime();
        return odt
    }
}

а затем вы можете аннотировать поле как

@CsvBindByName(converter = OffsetDateTimeConverter.class)
private OffsetDateTime time;

Быстрая демонстрация того, как работает этот синтаксический анализ:

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String strDate = "2020-09-18 06:50:00.000000";
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.n").withZone(ZoneId.systemDefault());
        ZonedDateTime zdt = ZonedDateTime.parse(strDate, dtf);
        OffsetDateTime odt = zdt.toOffsetDateTime();
        System.out.println(zdt);
        System.out.println(odt);
    }
}

Если вы используете OpenCSV 5

Вам не нужно определять класс преобразователя. Вы можете просто сделать это как

@CsvDate(value = "uuuu-MM-dd HH:mm:ss.n")
@CsvBindByName
private LocalDateTime time;
Другие вопросы по тегам