package nl.wldelft.timeseriesparsers;

import nl.wldelft.util.FastDateFormat;
import nl.wldelft.util.io.LineReader;
import nl.wldelft.util.io.TextParser;
import nl.wldelft.util.timeseries.DefaultTimeSeriesHeader;
import nl.wldelft.util.timeseries.TimeSeriesContentHandler;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

public class OttawaRiverRegulationPlanningBoardSHTTimeSeriesParser implements TextParser<TimeSeriesContentHandler> {

    public static final TimeZone EST = TimeZone.getTimeZone("EST");
    private static final FastDateFormat DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd", EST, Locale.CANADA, null);

    @Override
    public void parse(LineReader reader, String virtualFileName, TimeSeriesContentHandler contentHandler) throws Exception {

        String[] buffer = reader.readLine(' ');
        String forecastDateStart = buffer[buffer.length - 1];
        // This is the date when forecasting starts.
        Date date = DATE_FORMAT.parse(forecastDateStart);
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTimeZone(EST);
        calendar.setTime(date);
        DefaultTimeSeriesHeader forecastHeader = new DefaultTimeSeriesHeader();
        DefaultTimeSeriesHeader observationHeader = new DefaultTimeSeriesHeader();
        forecastHeader.setForecastTime(EST, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), 0);

        reader.skipLines(24);

        // Collecting days from the next row
        String[] days = reader.readLine(' ');

        reader.skipLines(3);

        // Finding out if there is a column with stars, separating the prior days
        int starIndex = -1;
        for (int i = 0; i < days.length; i++) {
            if (days[i].equals("*")) {
                // +2 is added because starting from the table rows, parameter and location columns are added too.
                starIndex = i + 2;
            }
        }

        // location and parameter are added since reading the next line
        buffer = new String[days.length + 2];
        reader.readLine(' ', buffer);
        // Until we reach the end of the table, in which case the length of the buffer would get 3.
        while (buffer.length > 3) {
            forecastHeader.setLocationId(buffer[0]);
            forecastHeader.setParameterId(buffer[1]);
            observationHeader.setLocationId(buffer[0]);
            observationHeader.setParameterId(buffer[1]);
            for (int i = 2; i < buffer.length; i++) {
                // Storing measurements
                if (i < starIndex) {
                    // The qualifier "Obs" is used for observation values
                    forecastHeader.setQualifierIds("Obs");
                    if (i == 2) {
                        calendar.add(Calendar.DAY_OF_YEAR, -(starIndex - 2));
                    } else {
                        calendar.add(Calendar.DAY_OF_YEAR, 1);
                    }
                    contentHandler.setTime(EST, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), 0);
                    contentHandler.setValue(Float.parseFloat(buffer[i]));
                    contentHandler.setTimeSeriesHeader(observationHeader);
                } else if (i > starIndex) {
                    // Storing forecast values
                    forecastHeader.setQualifierIds("Sim");
                    calendar.add(Calendar.DAY_OF_YEAR, 1);
                    contentHandler.setTime(EST, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), 0);
                    contentHandler.setValue(Float.parseFloat(buffer[i]));
                    contentHandler.setTimeSeriesHeader(forecastHeader);
                } else {
                    continue; // Do nothing when reaching the star column
                }

                contentHandler.applyCurrentFields();
            }
            calendar.setTime(date); // reset the date back to the forecasting date
            buffer = reader.readLine(' ');
        }
    }
}



  • No labels