UserData.java [src/WaterData] Revision: default Date:
package WaterData;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
/**
* Last Updated: 20-November-2018
* @author Tyler Wible
* @since 12-July-2012
*/
public class UserData {
/**
* Parses the supplied string of user data
* @param wqTest the water quality test desired "00600 Total nitrogen, water, unfiltered, milligrams per liter -- mg/L" (format: "5-digit test-name -- units") or "flow"
* @param startDate the user specified begin date, used to minimize the data returned
* @param endDate the user specified end date, used to minimize the data returned
* @return a string[][] with the contents of the user uploaded file formatted as: column1 = dates (yyyy-mm-dd),
* column2 = values (expected to be daily average flow values in cfs or water quality concentrations in the units of the current water quality test)
* if there is not a value for column2 (blank, null, not a number, etc.) then no data will be kept for that date
* @throws WaterDataException
*/
public static ArrayList<String> parseUserDataRaw(String userDataRaw, String startDate, String endDate, String wqTest) throws WaterDataException{
//Get today's date
DateFormat desiredDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date currentDate = new Date();
String todaysDate = desiredDateFormat.format(currentDate);
//Get the wqCode out of wqTest
String wqCode = wqTest;
if(wqTest.length() > 5){
wqCode = wqTest.substring(0,5);
}
//Get the headers and find the desired column of data
String[] userData_rows = userDataRaw.split("\n");
String[] headers = userData_rows[0].split("\t");
int headerIndex = -1;
for(int i=0; i<headers.length; i++){
if(headers[i].equalsIgnoreCase(wqCode)){
headerIndex = i;
}
}
//Check for lack of data
if(headerIndex == -1){
throw new WaterDataException("There is no uploaded data for water quality test:" + wqTest);
}
//Parse the user data
ArrayList<String> stationData = new ArrayList<>();
for(int i=1; i<userData_rows.length; i++){//Skip first row header
//Check for date format problems
String[] currentColumns = userData_rows[i].split("\t");
String correctedDate = fixDateFormat(currentColumns[0]);
//currentColumns[0] = date
//currentColumns[1] = value
//Only keep the data if the value column is not null
boolean valueExists = true;
try{
double value = Double.parseDouble(currentColumns[headerIndex]);
}catch(NullPointerException | NumberFormatException | ArrayIndexOutOfBoundsException e){
valueExists = false;
}
//If the date conversion does not hit an error keep this date
if(!correctedDate.equalsIgnoreCase("error") && valueExists){
//Check if the date is within the range the user desires
if(todaysDate.equals(endDate)){
//If the end limit is today, keep future forcasted data as well
if((correctedDate.compareTo(startDate) >= 0)){
stationData.add(correctedDate + "\t" + currentColumns[headerIndex]);
}
}else{
//Check if the current data is within the date range, if so keep it
if((correctedDate.compareTo(startDate) >= 0) && (correctedDate.compareTo(endDate) <= 0)){
stationData.add(correctedDate + "\t" + currentColumns[headerIndex]);
}
}
}
}
return stationData;
}
/**
* Converts the provided date format into a new date format of yyyy-mm-dd which is expected by all of the java functions (supported input formats are:
* yyyy-mm-dd,
* yyyy-mm-d,
* yyyy-m-dd,
* yyyy-m-d,
* yyyy/mm/dd,
* yyyy/mm/d,
* yyyy/m/dd,
* yyyy/m/d)
* @param date the original date format to be converted into yyyy-mm-dd
* @return the original date converted to the yyyy-mm-dd format or "error" if the date wasn't able to be converted
*/
public static String fixDateFormat(String date){
//This allows the user to upload a greater number of date formats that will be converted into the expected format for all the java interfaces
//Convert Determine the deliminator the current date format
String[] dateColumns = date.split("-");
String deliminator = "";
String day = "01", month = "01", year = "1900";
if(dateColumns.length != 1){
deliminator = "-";
}else{
//Not a "-" separated date, so try a "/" separated date
dateColumns = date.split("/");
if(dateColumns.length != 1){
deliminator = "/";
}else{
//Not a "/" separated date, so assume that it is a number and not parse-able as a date,
//return an error so this date can be skipped
return "error";
}
}
//Substring the date
String[] datePieces = date.split(deliminator);
year = datePieces[0];
month = datePieces[1];
day = datePieces[2];
//Check if user uploaded yyyy-MM-dd HH:mm data so shorted "day" accordingly
if(day.length() > 2){
day = day.substring(0,2);
}
//Check if the date pieces are the proper sizes (a 4 digit year, 2 digit month, and 2 digit day)
if(year.length() < 4 || year.length() > 4 || month.length() > 2 || day.length() > 2){
return "error";
}
//Check for a single digit month, if so make it a 2 digit month starting with a zero
if(month.length() < 2){
month = "0" + month;
}
//Check for a single digit day, if so make it a 2 digit day starting with a zero
if(day.length() < 2){
day = "0" + day;
}
//Assemble and return the newly formatted date
String newDate = year + "-" + month + "-" + day;
return newDate;
}
}