¿Como encontrar el último día hábil del mes en Java?
Quizas a usted alguna vez le toco programar como encontrar el último día hábil del mes. La definición:
Es el último día del mes, que no cae un fin de semana y que no es un día feriado.
Para trabajar este ejemplo utilizaremos fechas de los Estados Unidos, mercado de finanzas. En el caso de los días feriados, vamos a utilizar el calendario de OCC (Options Clearing Corporation). Dependiendo del área y país en donde usted trabaje el calendario de las fechas será distinto (por ejemplo Estados Unidos y Venezuela).
La solución en Java es sencilla, usando la clase Calendar. Después de jugar un poco al final terminé escribiendo esta clase que muestra el último día hábil del mes y le dice a usted si la fecha entrada por el teclado es un día hábil o no:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | package com.kodegeek.blog.finance; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.ResourceBundle; import java.util.Scanner; import java.util.Set; import java.util.logging.Logger; /** * Helper date methods tailored for the financial industry. * License: LGPL * BLOG: http://kodegeek.com * @author josevnz@kodegeek.com * */ public final class DateHelper { private final static ResourceBundle BUNDLE; private final static Logger log; private static final Set holidays; static { BUNDLE = ResourceBundle.getBundle(DateHelper.class.getName()); log = Logger.getLogger(DateHelper.class.getName()); // Populate the holidays set holidays = new HashSet(); for (String dateStr: BUNDLE.getString("com.kodegeek.blog.finance.DateHelper.holidays").split(";\\s*", -1)) { try { holidays.add(DateFormat.getDateInstance(DateFormat.DEFAULT).parse(dateStr)); } catch (ParseException e) { log.warning(String.format(BUNDLE.getString("com.kodegeek.blog.finance.DateHelper.error.badDate"), dateStr)); continue; } } } /** * Default constructor */ private DateHelper() { // Only static methods go on this class } /** * Check if a given date is the last business day of the month * @param aDate The date to test * @return True if is the last day of the month, false otherwise */ public final static boolean isLastBusinessDayOfMonth(final Date aDate) { boolean isLastBusinessDay = false; // Can do a comparison? if (aDate == null) { return isLastBusinessDay; } Calendar calendar = Calendar.getInstance(); // Current date on a weekend calendar.setTime(aDate); int day = calendar.get(Calendar.DAY_OF_MONTH); int month = calendar.get(Calendar.MONTH); int year = calendar.get(Calendar.YEAR); int lastbusinessDayOfMonth = getLastBusinessDayOfMonth(month, year); if (lastbusinessDayOfMonth == day) { isLastBusinessDay = true; } return isLastBusinessDay; } /** * Get the last business day of the month for a given month / year combination * @param month The month * @param year The year * @return The last business day */ public static int getLastBusinessDayOfMonth(final int month, final int year) { int day = -1; Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.MONTH, month); calendar.set(Calendar.YEAR, year); calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); // Keep looking backwards until the day is not a weekend or a holiday while(true) { if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) { calendar.add(Calendar.DAY_OF_MONTH, -1); continue; } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { calendar.add(Calendar.DAY_OF_MONTH, -2); continue; } else if (holidays.contains(calendar.getTime())) { calendar.add(Calendar.DAY_OF_MONTH, -1); continue; } break; } // End while day = calendar.get(Calendar.DAY_OF_MONTH); return day; } /** * Unit test, load today date and check if is a end of the month * @param args The date to test from the command line * @throws Exception If the date is invalid for the given local */ public static void main(String [] args) throws Exception { Scanner scan = new Scanner(System.in); do { String currDateStr = null; SimpleDateFormat format = new SimpleDateFormat("yy-M-d"); try { System.out.println("Please enter a date to check (YYYY-MM-DD, Ctrl-C to exit):"); currDateStr = scan.nextLine(); Date date = format.parse(currDateStr); if (date != null) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); int month = calendar.get(Calendar.MONTH); int year = calendar.get(Calendar.YEAR); System.out.println(String.format("Last business day of the month: %d", getLastBusinessDayOfMonth(month, year))); System.out.println(String.format("%s %s", currDateStr,isLastBusinessDayOfMonth(date) == true? "Is the last business day": "Is not the last business day")); } } catch (ParseException pExp) { System.err.println(String.format("Ignoring bad date: '%s'", currDateStr)); } } while (true); } } |
El resource bundle lo único que contiene son los días feriados:
1 2 3 | # Bank holidays per OCC calendar 2009 - http://www.optionsclearing.com/market/infomemos/2008/oct/24961.pdf com.kodegeek.blog.finance.DateHelper.holidays=Jan 01, 2009;January 19, 2009; Feb 26, 2009;Apr 10, 2009;May 25, 2009;July 3, 2009; Sep 7, 2009; Nov 26, 2009; Dec 25, 2009; Oct 12, 2009; Nov 11, 2009 com.kodegeek.blog.finance.DateHelper.error.badDate=Got bad date '%s' from property |
La idea es buscar el último día del mes y de allí contar hacia atrás, esquivando fines de semana y días feriados.
Please enter a date to check (YYYY-MM-DD, Ctrl-C to exit):
2009-02-27
Last business day of the month: 27
2009-02-27 Is the last business day
En una siguiente entrega les mostraré como hacer lo mismo en Ruby.
Blogalaxia:calendar, calendario, java.perl.ruby, occ
Technorati:calendar, calendario, java.perl.ruby, occ
To2blogs:calendar, calendario, java.perl.ruby, occ
Del.icio.us:calendar, calendario, java.perl.ruby, occ
Comentarios recientes