com.leonarduk.finance.utils.DateUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.leonarduk.finance.utils.DateUtils.java

Source

/*
 * Copyright (c) 2011 Kevin Sawicki <kevinsawicki@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.leonarduk.finance.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import org.joda.time.DateTimeConstants;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.leonarduk.finance.stockfeed.yahoo.YahooFeed;

import jersey.repackaged.com.google.common.collect.Maps;

/**
 * Helpers for common dates
 */
public class DateUtils {
    private static Map<String, Date> dates;

    public static final Logger logger = LoggerFactory.getLogger(DateUtils.class.getName());

    public static Calendar dateToCalendar(final Date date) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar;
    }

    public static Calendar dateToCalendar(final LocalDate fromDate) {
        return DateUtils.dateToCalendar(fromDate.toDate());
    }

    public static int getDiffInWorkDays(final LocalDate currentDate, final LocalDate nextDate) {
        final int calendarDaysDiff = Math.abs(Days.daysBetween(nextDate, currentDate).getDays());
        final int weeks = Math.round(calendarDaysDiff / 7);
        return Math.abs((5 * weeks) + Math.min(calendarDaysDiff % 7, 5));
    }

    private static String getDividendDateFormat(final String date) {
        if (date.matches("[0-9][0-9]-...-[0-9][0-9]")) {
            return "dd-MMM-yy";
        } else if (date.matches("[0-9]-...-[0-9][0-9]")) {
            return "d-MMM-yy";
        } else if (date.matches("...[ ]+[0-9]+")) {
            return "MMM d";
        } else {
            return "M/d/yy";
        }
    }

    public static Iterator<LocalDate> getLocalDateIterator(final LocalDate startDate, final LocalDate lastDate) {
        return new Iterator<LocalDate>() {

            LocalDate nextDate = startDate;

            @Override
            public boolean hasNext() {
                return this.nextDate.isBefore(lastDate) || this.nextDate.equals(lastDate);
            }

            @Override
            public LocalDate next() {
                final LocalDate currentDate = this.nextDate;
                if (this.nextDate.getDayOfWeek() == DateTimeConstants.FRIDAY) {
                    this.nextDate = this.nextDate.plusDays(2);
                }
                this.nextDate = this.nextDate.plusDays(1);
                return currentDate;
            }

        };

    }

    public static Iterator<LocalDate> getLocalDateNewToOldIterator(final LocalDate startDate,
            final LocalDate lastDate) {
        return new Iterator<LocalDate>() {

            LocalDate nextDate = startDate;

            @Override
            public boolean hasNext() {
                return this.nextDate.isAfter(lastDate) || this.nextDate.equals(lastDate);
            }

            @Override
            public LocalDate next() {
                if (this.nextDate.getDayOfWeek() == DateTimeConstants.SUNDAY) {
                    this.nextDate = this.nextDate.minusDays(2);
                }
                if (this.nextDate.getDayOfWeek() == DateTimeConstants.SATURDAY) {
                    this.nextDate = this.nextDate.minusDays(1);
                }
                final LocalDate currentDate = this.nextDate;
                this.nextDate = this.nextDate.minusDays(1);
                return currentDate;
            }

        };

    }

    public static LocalDate getPreviousDate(final LocalDate currentDate) {
        final LocalDate returnDate = currentDate.minusDays(1);
        if ((returnDate.getDayOfWeek() == DateTimeConstants.SATURDAY)
                || (returnDate.getDayOfWeek() == DateTimeConstants.SUNDAY)) {
            return DateUtils.getPreviousDate(returnDate);
        }
        return returnDate;
    }

    public static Date parseDate(final String fieldValue) throws ParseException {
        if (null == DateUtils.dates) {
            DateUtils.dates = Maps.newConcurrentMap();
        }
        return (DateUtils.dates.computeIfAbsent(fieldValue, v -> LocalDate.parse(v).toDate()));
    }

    /**
     * Used to parse the last trade date / time. Returns null if the date / time
     * cannot be parsed.
     *
     * @param date
     *            String received that represents the date
     * @param time
     *            String received that represents the time
     * @param timeZone
     *            time zone to use for parsing the date time
     * @return Calendar object with the parsed datetime
     */
    public static Calendar parseDateTime(final String date, final String time, final TimeZone timeZone) {
        final String datetime = date + " " + time;
        final SimpleDateFormat format = new SimpleDateFormat("M/d/yyyy h:mma", Locale.US);

        format.setTimeZone(timeZone);
        try {
            if (StringUtils.isParseable(date) && StringUtils.isParseable(time)) {
                final Calendar c = Calendar.getInstance();
                c.setTime(format.parse(datetime));
                return c;
            }
        } catch (final ParseException ex) {
            DateUtils.logger.warn("Failed to parse datetime: " + datetime);
            DateUtils.logger.trace("Failed to parse datetime: " + datetime, ex);
        }
        return null;
    }

    /**
     * Used to parse the dividend dates. Returns null if the date cannot be
     * parsed.
     *
     * @param date
     *            String received that represents the date
     * @return Calendar object representing the parsed date
     */
    public static Calendar parseDividendDate(final String date) {
        if (!StringUtils.isParseable(date)) {
            return null;
        }
        final SimpleDateFormat format = new SimpleDateFormat(DateUtils.getDividendDateFormat(date.trim()),
                Locale.US);
        format.setTimeZone(TimeZone.getTimeZone(YahooFeed.TIMEZONE));
        try {
            final Calendar today = Calendar.getInstance(TimeZone.getTimeZone(YahooFeed.TIMEZONE));
            final Calendar parsedDate = Calendar.getInstance(TimeZone.getTimeZone(YahooFeed.TIMEZONE));
            parsedDate.setTime(format.parse(date.trim()));

            if (parsedDate.get(Calendar.YEAR) == 1970) {
                // Not really clear which year the dividend date is... making a
                // reasonable guess.
                final int monthDiff = parsedDate.get(Calendar.MONTH) - today.get(Calendar.MONTH);
                int year = today.get(Calendar.YEAR);
                if (monthDiff > 6) {
                    year -= 1;
                } else if (monthDiff < -6) {
                    year += 1;
                }
                parsedDate.set(Calendar.YEAR, year);
            }

            return parsedDate;
        } catch (final ParseException ex) {
            DateUtils.logger.warn("Failed to parse dividend date: " + date);
            DateUtils.logger.trace("Failed to parse dividend date: " + date, ex);
            return null;
        }
    }

}