All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.zavtech.morpheus.yahoo.YahooFinanceParser Maven / Gradle / Ivy

/**
 * Copyright (C) 2014-2017 Xavier Witdouck
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.zavtech.morpheus.yahoo;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A parser that can parse string content from Yahoo Finance into an appropriate Java type.
 *
 * @author Xavier Witdouck
 *
 * 

This is open source software released under the Apache 2.0 License

*/ public class YahooFinanceParser { private static final Map monthMap = new HashMap<>(); private Matcher numberMatcher1 = Pattern.compile("^\\+?(-?\\d*\\.?\\d*)([KMB]?)$", Pattern.CASE_INSENSITIVE).matcher(""); private Matcher numberMatcher2 = Pattern.compile("^\\+?(-?[\\d,]*\\.?\\d*)$", Pattern.CASE_INSENSITIVE).matcher(""); private Matcher percentMatcher = Pattern.compile("^\\+?(-?\\d*\\.?\\d*)%$", Pattern.CASE_INSENSITIVE).matcher(""); private Matcher dateMatcher1 = Pattern.compile("^([\\p{Alpha}]{3})\\s([0-9]{1,2})$", Pattern.CASE_INSENSITIVE).matcher(""); private Matcher dateMatcher2 = Pattern.compile("^([\\p{Alpha}]{3})\\s([0-9]{1,2}),\\s([0-9]{4})$", Pattern.CASE_INSENSITIVE).matcher(""); private Matcher dateMatcher3 = Pattern.compile("^(\\d+)/(\\d+)/(\\d+)$", Pattern.CASE_INSENSITIVE).matcher(""); private Matcher timeMatcher1 = Pattern.compile("(\\d+):(\\d+)(am|pm)$", Pattern.CASE_INSENSITIVE).matcher(""); /** * Static initializer */ static { monthMap.put("jan", 1); monthMap.put("feb", 2); monthMap.put("mar", 3); monthMap.put("apr", 4); monthMap.put("may", 5); monthMap.put("jun", 6); monthMap.put("jul", 7); monthMap.put("aug", 8); monthMap.put("sep", 9); monthMap.put("oct", 10); monthMap.put("nov", 11); monthMap.put("dec", 12); } /** * Attempts to parse the string into another type * @param value the value to parse * @return the parsed value */ public Object parse(String value) { try { if (value == null) return null; else if (value.equalsIgnoreCase("-")) return null; else if (value.equalsIgnoreCase("N/A")) return null; else if (value.equalsIgnoreCase("NaN")) return null; else if (numberMatcher1.reset(value.replace("," , "")).matches()) { final String token1 = numberMatcher1.group(1); final String token2 = numberMatcher1.group(2); final double number = Double.parseDouble(token1); if (token2 == null || token2.length() == 0) return number; else if (token2.equalsIgnoreCase("K")) return number * 1000d; else if (token2.equalsIgnoreCase("M")) return number * 1000000d; else if (token2.equalsIgnoreCase("B")) return number * 1000000000d; else return number; } else if (numberMatcher2.reset(value.replace("," , "")).matches()) { final String token = numberMatcher2.group(1); final String stripped = token.replace(",", ""); return Double.parseDouble(stripped); } else if (percentMatcher.reset(value.replace("," , "")).matches()) { final String token = percentMatcher.group(1); final double number = Double.parseDouble(token); return number / 100d; } else if (dateMatcher1.reset(value).matches()) { final String monthString = dateMatcher1.group(1); final String dateString = dateMatcher1.group(2); final int year = LocalDate.now().getYear(); final Integer month = monthMap.get(monthString.toLowerCase()); if (month == null) throw new RuntimeException("Unsupported month: " + monthString); return LocalDate.of(year, month, Integer.parseInt(dateString)); } else if (dateMatcher2.reset(value).matches()) { final String monthString = dateMatcher2.group(1); final String dateString = dateMatcher2.group(2); final int year = Integer.parseInt(dateMatcher2.group(3)); final Integer month = monthMap.get(monthString.toLowerCase()); if (month == null) throw new RuntimeException("Unsupported month $monthString"); return LocalDate.of(year, month, Integer.parseInt(dateString)); } else if (dateMatcher3.reset(value).matches()) { final String monthString = dateMatcher3.group(1); final String dateString = dateMatcher3.group(2); final int year = Integer.parseInt(dateMatcher3.group(3)); final int month = Integer.parseInt(monthString); return LocalDate.of(year, month, Integer.parseInt(dateString)); } else if (timeMatcher1.reset(value).matches()) { final int hour = Integer.parseInt(timeMatcher1.group(1)); final int minutes = Integer.parseInt(timeMatcher1.group(2)); final boolean am = timeMatcher1.group(3).equalsIgnoreCase("am"); if (am) { switch (hour) { case 12: return LocalTime.of(0, minutes); default: return LocalTime.of(hour, minutes); } } else { switch (hour) { case 12: return LocalTime.of(hour, minutes); default: return LocalTime.of(12 + hour, minutes); } } } else { return value; } } catch (Throwable ex) { throw new YahooException("Failed to parse value: " + value, ex); } } /** * Returns a double value parsed from the string * @param value the text value * @return the double value */ public double parseDouble(String value) { if (value == null) { return Double.NaN; } else { value = value.trim(); if (value.length() == 0 || value.equalsIgnoreCase("N/A") || value.equalsIgnoreCase("-")) { return Double.NaN; } else { final Object result = parse(value); if (result instanceof Number) { return ((Number) result).doubleValue(); } else { throw new RuntimeException("Failed to parse value into double, returned result: " + value); } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy