Java tutorial
/* jBilling - The Enterprise Open Source Billing System Copyright (C) 2003-2011 Enterprise jBilling Software Ltd. and Emiliano Conde This file is part of jbilling. jbilling is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. jbilling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with jbilling. If not, see <http://www.gnu.org/licenses/>. */ package com.sapienter.jbilling.server.process; import com.sapienter.jbilling.common.SessionInternalError; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.joda.time.DateMidnight; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; /** * Utilities for calculating dates and dealing with business days (aka, banking days). * * @author Vikas Bodani, Brian Cowdery * @since 29/04/11 */ public class BusinessDays { private static final Logger LOG = Logger.getLogger(BusinessDays.class); private static final DateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); private List<Date> holidays = new ArrayList<Date>(); private Calendar start = GregorianCalendar.getInstance(); private Calendar end = GregorianCalendar.getInstance(); public BusinessDays() { } public BusinessDays(List<Date> holidays) { this.holidays = holidays; } public BusinessDays(File holidayFile) { loadHolidayFile(holidayFile); } public BusinessDays(File holidayFile, DateFormat dateformat) { loadHolidayFile(holidayFile, dateformat); } /** * Loads an external file containing the dates of holidays. These days will be handled * as non-business days when calculating business dates. * * This method assumes a default date format of "yyyy-MM-dd". * * @param file files to load */ public void loadHolidayFile(File file) { loadHolidayFile(file, DEFAULT_DATE_FORMAT); } /** * Loads an external file containing the dates of holidays. These days will be handled * as non-business days when calculating business dates. * * @param file files to load * @param dateFormat date format of dates */ public void loadHolidayFile(File file, DateFormat dateFormat) { holidays.clear(); if (file != null && file.exists()) { BufferedReader in = null; try { in = new BufferedReader(new FileReader(file)); String line = null; while ((line = in.readLine()) != null) { if (StringUtils.isNotBlank(line)) { try { Date holiday = dateFormat.parse(line); holidays.add(holiday); } catch (ParseException e) { LOG.warn("Invalid holiday date, or wrong date format - ignoring entry '" + line + "'"); } } } } catch (IOException e) { LOG.warn("Holiday file " + file.getPath() + " could not be read."); } finally { try { if (in != null) { in.close(); } } catch (IOException e) { /* ignore */ } } } else { LOG.warn("Holiday file not set or does not exist."); } } /** * Convert a non-business day range and calculate an appropriate end date that falls on * a business day. If the original date range contains a weekend day or holiday, then the * resulting end date will be incremented as to exclude it. * * @param startDate starting date * @param endDate ending date * @return new end date for a business-day date range */ public Date calculateEndDate(Date startDate, Date endDate) { start.setTime(startDate); end.setTime(endDate); while (start.before(end)) { if (start.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || start.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { end.add(Calendar.DATE, 1); } else { for (Date holiday : holidays) { if (isEqual(holiday, start.getTime())) { end.add(Calendar.DATE, 1); } } } start.add(Calendar.DATE, 1); } return end.getTime(); } /** * Adds the given number of business days to the starting date. * * @param startDate initial start date to add days to * @param days business days to add * @return date with business days added */ public Date addBusinessDays(Date startDate, int days) { start.setTime(startDate); int nonBusinessDays = 0; for (int i = 0; i < days; i++) { start.add(Calendar.DATE, 1); if (start.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || start.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { nonBusinessDays++; } for (Date holiday : holidays) { if (isEqual(holiday, start.getTime())) { nonBusinessDays++; } } } start.add(Calendar.DATE, nonBusinessDays); return start.getTime(); } private boolean isEqual(Date startDate, Date endDate) { return new DateMidnight(startDate).equals(new DateMidnight(endDate)); } }