Last active
December 18, 2015 16:09
-
-
Save ameron32/5809822 to your computer and use it in GitHub Desktop.
For [doggxyo]. His spreadsheet converted into a console-based java program.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.YOURPACKAGE.CHANGEMEBEFOREUSINGME; | |
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import java.util.ArrayList; | |
import java.util.Date; | |
import java.util.GregorianCalendar; | |
import java.util.List; | |
import java.util.Locale; | |
import java.util.Scanner; | |
public class Test { | |
// these are the placeholders reserved for storing date information to use repeatedly | |
static Date start, end; | |
static Date startOfDay, endOfDay; | |
static List<Date> holidays = new ArrayList<Date>(); | |
// this is the conversion formula reserved for use throughout the program | |
static int mSecInOneHour = (1000 * 60 * 60); // to convert milliseconds to hours | |
static long mSecInOneDay = mSecInOneHour * 24; // to convert milliseconds to days | |
// re-calculates during interaction | |
static int hoursPerBusinessDay; | |
// this is the text input for the console | |
static Scanner scan; | |
// more detailed logging in the console if isLogging is set to true | |
static boolean isLogging = false; | |
// formats to be used throughout the program | |
// references to display to the user (change these to change what the user | |
// sees) | |
static String timeFormatRef = "24Hour:Minute"; | |
static String dateFormatRef = "Month/day/year"; | |
static String dateAndTimeFormatRef = dateFormatRef + " " + timeFormatRef; | |
// format to give to conversion tools in java (change these to change what | |
// to give the java utilities, only if you know what you are trying to do | |
// and how to do it) | |
static String timeFormatCalc = "h:mm"; | |
static String dateFormatCalc = "M/d/yyyy"; | |
static String dateMiniFormatCalc = "M/d"; | |
static String dateAndTimeFormatCalc = dateFormatCalc + " " + timeFormatCalc; | |
/** | |
* Where it all begins... | |
* | |
* @param Not needed. | |
*/ | |
public static void main(String[] args) { | |
prepare(); | |
displayInstructions(); | |
showData(); | |
askForCommand(); | |
} | |
/** | |
* Performs all initialization activities, including setting defaults | |
*/ | |
private static void prepare() { | |
scan = new Scanner(System.in); | |
// set default start and stop times here | |
start = convertStringToDate("07/02/2013 09:00"); | |
end = convertStringToDate("07/05/2013 17:00"); | |
// set default business day here | |
startOfDay = convertStringToDate("09:00"); | |
endOfDay = convertStringToDate("17:00"); | |
hoursPerBusinessDay = 8; | |
// load default holidays 2013 into a list of holidays to review later | |
holidays.add(convertStringToDate("1/1/2013")); // New Years | |
holidays.add(convertStringToDate("1/21/2013")); // MLK day | |
holidays.add(convertStringToDate("2/18/2013")); // Washington's Birthday | |
holidays.add(convertStringToDate("5/27/2013")); // Memorial day | |
holidays.add(convertStringToDate("7/4/2013")); // Independence day | |
holidays.add(convertStringToDate("9/2/2013")); // Labor day | |
holidays.add(convertStringToDate("10/14/2013")); // Columbus day | |
holidays.add(convertStringToDate("11/11/2013")); // Veterans day | |
holidays.add(convertStringToDate("11/28/2013")); // Thanksgiving | |
holidays.add(convertStringToDate("12/25/2013")); // Christmas | |
// load default holidays 2014 | |
holidays.add(convertStringToDate("1/1/2014")); // New Years | |
holidays.add(convertStringToDate("1/21/2014")); // MLK day | |
holidays.add(convertStringToDate("2/18/2014")); // Washington's Birthday | |
holidays.add(convertStringToDate("5/27/2014")); // Memorial day | |
holidays.add(convertStringToDate("7/4/2014")); // Independence day | |
holidays.add(convertStringToDate("9/2/2014")); // Labor day | |
holidays.add(convertStringToDate("10/14/2014")); // Columbus day | |
holidays.add(convertStringToDate("11/11/2014")); // Veterans day | |
holidays.add(convertStringToDate("11/28/2014")); // Thanksgiving | |
holidays.add(convertStringToDate("12/25/2014")); // Christmas | |
} | |
/** | |
* Displays the list of commands to the user. | |
*/ | |
private static void displayInstructions() { | |
// displays the instructions to the user | |
display("Put your opening comments here."); | |
display("Commands: hours, start, end, holidaylist, show, go, help, quit"); | |
display("---hours: set the business hours each day"); | |
display("---start: set the start date and time"); | |
display("---end: set the end date and time"); | |
display("---holidaylist: set the yearly holidays [not yet implemented]"); | |
display("---show: show the current settings"); | |
display("---log: toggles logging"); | |
display("---go: display the result"); | |
display("---help: show these commands"); | |
display("---quit: quit, of course"); | |
} | |
/** | |
* Displays the current settings to the user. | |
*/ | |
private static void showData() { | |
// convert the dates into formatted strings | |
String formattedStartOfDay = convertDateToFormattedString(startOfDay, timeFormatCalc); | |
String formattedEndOfDay = convertDateToFormattedString(endOfDay, timeFormatCalc); | |
String formattedStartDay = convertDateToFormattedString(start, dateAndTimeFormatCalc); | |
String formattedEndDay = convertDateToFormattedString(end, dateAndTimeFormatCalc); | |
// display the formatted information on screen | |
display("Business Day: " + formattedStartOfDay + " to " + formattedEndOfDay); | |
display("Business Hours: " + hoursPerBusinessDay); | |
display("DayStart: " + formattedStartDay); | |
display("DayEnd: " + formattedEndDay); | |
} | |
/** | |
* Handles requesting a user input and then performing the appropriate action based on that input | |
*/ | |
private static void askForCommand() { | |
String command = requestCommandInput(); | |
processCommandInputs(command); | |
} | |
/** | |
* Prompts user to enter a command and silently checks to see if the user | |
* entered a "quit" command, handling the command accordingly. | |
* | |
* @return The user input string. | |
*/ | |
private static String requestCommandInput() { | |
display("Enter Command:"); | |
String s = scan.nextLine(); | |
checkForProgramQuit(s); | |
return s; | |
} | |
/** | |
* Chooses which action to take based on the command entered by the user and then performs that action. | |
* | |
* @param A string generally expected to be a user-input command string. | |
*/ | |
private static void processCommandInputs(String s) { | |
// compare the command string against the list of pre-programmed commands to determine the action to take | |
if (s.equalsIgnoreCase("hours")) { | |
// request from user DayStart and DayEnd times | |
display("Please enter the time of Start of Business."); | |
display("Format: " + timeFormatRef); | |
startOfDay = requestDate(); | |
display("Please enter the time of End of Business."); | |
display("Format: " + timeFormatRef); | |
endOfDay = requestDate(); | |
recalcBusinessHours(); | |
} else if (s.equalsIgnoreCase("start")) { | |
// request from user start date | |
display("Please enter the start date and time to calculate."); | |
display("Format: " + dateAndTimeFormatRef); | |
start = requestDate(); | |
} else if (s.equalsIgnoreCase("end")) { | |
// request from user end date | |
display("Please enter the end date and time to calculate."); | |
display("Format: " + dateAndTimeFormatRef); | |
end = requestDate(); | |
} else if (s.equalsIgnoreCase("show")) { | |
showData(); | |
} else if (s.equalsIgnoreCase("holidaylist")) { | |
// TODO add code to change holidaylist | |
; | |
} else if (s.equalsIgnoreCase("go")) { | |
go(); | |
} else if (s.equalsIgnoreCase("?") || | |
s.equalsIgnoreCase("help") || | |
s.equalsIgnoreCase("command") || | |
s.equalsIgnoreCase("commands")) { | |
displayInstructions(); | |
} else if (s.equalsIgnoreCase("log")) { | |
// toggles logging | |
display("Logging is now " + ((isLogging) ? "on" : "off") + "."); | |
isLogging = !isLogging; | |
} else { | |
// tell the user the command was invalid and allow the user to try again | |
display("Unknown Command"); | |
} | |
// no matter what the command was, ask for the next command | |
askForCommand(); | |
} | |
/** | |
* When called, recalculates the total hours of a business day based on the startOfDay and endOfDay times input by user or by default. | |
*/ | |
private static void recalcBusinessHours() { | |
hoursPerBusinessDay = (int) Math.floor((endOfDay.getTime() - startOfDay.getTime()) / mSecInOneHour); | |
} | |
/** | |
* Prompts user to enter a date and/or time and silently checks to see if | |
* the user entered a "quit" command, handling the command accordingly. | |
* | |
* @return A date converted from the user entered string. | |
*/ | |
private static Date requestDate() { | |
display("Enter Date and/or Time: "); | |
String s = scan.nextLine(); | |
checkForProgramQuit(s); | |
Date date = convertStringToDate(s); | |
return date; | |
} | |
/** | |
* Attempts to convert the string parameter into a date. If the conversion | |
* fails, prompts the user to enter a valid input again. This method loops | |
* until a valid string is provided or the user enters a "quit" command. | |
* | |
* @param A string which is formatted correctly to be converted into a date. | |
* @return A date equal to the string entered, if possible. | |
*/ | |
private static Date convertStringToDate(String string) { | |
Date date; | |
date = convertStringToDateFormat(string, dateAndTimeFormatCalc); | |
if (date == null) | |
date = convertStringToDateFormat(string, dateFormatCalc); | |
if (date == null) | |
date = convertStringToDateFormat(string, dateMiniFormatCalc); | |
if (date == null) | |
date = convertStringToDateFormat(string, timeFormatCalc); | |
if (date == null) { | |
// the date could not convert, notify user then allow them to try again | |
display("Your input: [" + string + "] does not convert. "); | |
display("If all else fails, please try '" + dateAndTimeFormatRef + "' format."); | |
display("An example looks like: " + "07/01/2013 17:00"); | |
// request user input again | |
date = requestDate(); | |
} | |
return date; | |
} | |
/** | |
* Helper method for convertStringToDate(string) | |
* | |
* @param String to convert | |
* @param String of date/time template to compare against. | |
* @return A date from the string | |
*/ | |
private static Date convertStringToDateFormat(String string, String format) { | |
try { | |
return new SimpleDateFormat(format, Locale.ENGLISH).parse(string.trim()); | |
} catch (ParseException e) { | |
// do not display failed attempts to convert | |
} | |
return null; | |
} | |
/** | |
* Helper method to convert a date back into a string for displaying to the user. | |
* | |
* @param A date to convert to a string | |
* @param String of date/time format to convert into. | |
* @return A string formatted like the format string from the date parameter. | |
*/ | |
private static String convertDateToFormattedString(Date date, String format) { | |
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.ENGLISH); | |
return sdf.format(date); | |
} | |
/** | |
* Main method to perform the logic of the calculation. This method compares | |
* the start and end date/times to determine the working hours between them. | |
* In short, this method loops through each day between the start date and | |
* the end date and checks for holidays, weekends, and actual business hours | |
* each day. The primary loop used is | |
* calculateBusinessHoursInTheDay(calendar). | |
*/ | |
private static void go() { | |
// calculate hours | |
int hours = 0; | |
// find the difference in the time between End and Start (End - Start) in Days | |
int numberOf24HourDays = (int) Math.floor((end.getTime() | |
- start.getTime()) | |
/ mSecInOneDay); | |
// if the difference in days is not perfectly even, assume one more day | |
// [for example: midnight to midnight = 3.0 days, but midnight to noon = 3.5 days. this would make it 4 days to check] | |
if (((end.getTime() - start.getTime()) % mSecInOneDay) != 0) { | |
numberOf24HourDays += 1; | |
} | |
GregorianCalendar cal = new GregorianCalendar(); | |
cal.setTime(start); | |
log("C: " + cal.getTime().toString()); | |
// daily loop, which checks how many working hours in the given day. | |
for (int i = 0; i < numberOf24HourDays; i++) { | |
hours += calculateBusinessHoursInTheDay(cal); | |
cal.add(GregorianCalendar.DATE, 1); | |
} | |
// convert the final total business working hours to days & hours | |
int resultDays = (int) Math.floor(hours / hoursPerBusinessDay); // TODO is this 8 hour days or calculated business days? | |
int resultHours = (hours % hoursPerBusinessDay); | |
// display results | |
showData(); | |
display(hours + " total hours"); | |
display(resultDays + " days, " + resultHours + " hours"); | |
askForCommand(); | |
} | |
/** | |
* The complex logic of the program. Determine if a given day is (a) a | |
* holiday, (b) a weekend, (c) the first of the last day of the calculation, | |
* which could be a partial day, or (d) a standard, full day. | |
* | |
* @param dateIn | |
* @return | |
*/ | |
private static int calculateBusinessHoursInTheDay(GregorianCalendar dateIn) { | |
// prepare for heavy math | |
Date date = trimTimeOffDate(dateIn.getTime()); | |
log("[Date] " + date.toString()); | |
GregorianCalendar calendarDate = new GregorianCalendar(Locale.ENGLISH); | |
calendarDate.setTime(date); | |
GregorianCalendar startCalendarDate = new GregorianCalendar(Locale.ENGLISH); | |
startCalendarDate.setTime(start); | |
GregorianCalendar endCalendarDate = new GregorianCalendar(Locale.ENGLISH); | |
endCalendarDate.setTime(end); | |
// compare this date against every holiday, return 0 working hours | |
// if this date matches a holiday | |
for (Date holiday : holidays) { | |
if (date.equals(holiday)) { | |
log("Holiday " + 0 + " hours"); | |
return 0; | |
} | |
} | |
// if this date is the weekend, return 0 working hours | |
if (calendarDate.get(GregorianCalendar.DAY_OF_WEEK) == GregorianCalendar.SUNDAY || | |
calendarDate.get(GregorianCalendar.DAY_OF_WEEK) == GregorianCalendar.SATURDAY) { | |
log("Weekend " + 0 + " hours"); | |
return 0; | |
} | |
long totalMillis = 0l; | |
// if start and end occur in the same day | |
if ((endCalendarDate.getTimeInMillis() - startCalendarDate.getTimeInMillis()) < mSecInOneDay) { | |
long mSecStart = startCalendarDate.getTimeInMillis() % mSecInOneDay; | |
long mSecEnd = endCalendarDate.getTimeInMillis() % mSecInOneDay; | |
totalMillis += (mSecEnd - mSecStart); | |
log((totalMillis / mSecInOneDay) + "/" + (mSecStart / mSecInOneDay) | |
+ "/" + (mSecEnd / mSecInOneDay)); | |
// if start is before beginning of business day, subtract the time before business day starts | |
if (mSecStart < startOfDay.getTime()) { | |
log("Starts Before Business Day"); | |
totalMillis -= startOfDay.getTime() - mSecStart; | |
} | |
// if end is after end of business day, subtract the time after business day ends | |
if (mSecEnd > endOfDay.getTime()) { | |
log("Ends After Business Day"); | |
totalMillis -= endOfDay.getTime() - mSecEnd; | |
} | |
int sameDay = ((int) Math.floor(totalMillis / mSecInOneHour)); | |
log("Same Day " + sameDay + " hours"); | |
return sameDay; | |
} | |
// if this date is less than 24 hours from start date/time, ... | |
else if (((startCalendarDate.getTimeInMillis() - calendarDate.getTimeInMillis()) >= 0) && | |
((calendarDate.getTimeInMillis() - startCalendarDate.getTimeInMillis()) < mSecInOneDay)) { | |
// calculate and convert the hours from this day | |
totalMillis += (calendarDate.getTimeInMillis() + mSecInOneDay) - startCalendarDate.getTimeInMillis(); | |
// subtract the post-business evening hours | |
long businessTotalMillis = totalMillis - (endOfDay.getTime() - mSecInOneDay); | |
// if there is no time remaining (the start time was after end of business), return 0 hours | |
if (businessTotalMillis <= 0) { | |
return 0; | |
} else { | |
// if the time remaining in the business day is more than the hours in a business day | |
// (the start time was before start of business) | |
// return the number of hours in a full business day | |
int mSecInOneBusinessDay = (int)(endOfDay.getTime() - startOfDay.getTime()); | |
if (businessTotalMillis > mSecInOneBusinessDay) { | |
log(((int)Math.floor(mSecInOneBusinessDay / mSecInOneHour)) + ""); | |
int startDay = ((int)Math.floor(mSecInOneBusinessDay / mSecInOneHour)); | |
log("Start Day " + startDay + " hours"); | |
return startDay; | |
} | |
} | |
} | |
// if this date is less than 24 hours from the end date/time, ... | |
else if (((endCalendarDate.getTimeInMillis() - calendarDate.getTimeInMillis()) >= 0) && | |
((endCalendarDate.getTimeInMillis() - calendarDate.getTimeInMillis()) < mSecInOneDay)) { | |
// calculate and convert the hours from this day | |
totalMillis += endCalendarDate.getTimeInMillis() - calendarDate.getTimeInMillis(); | |
// subtract the pre-business morning hours | |
long businessTotalMillis = totalMillis - startOfDay.getTime(); | |
// if there is no time remaining (the end time was before start of business), return 0 hours | |
if (businessTotalMillis <= 0) { | |
return 0; | |
} else { | |
// if the time remaining in the business day is more than the hours in a business day | |
// (the end time was after close of business) | |
// return the number of hours in a full business day | |
int mSecInOneBusinessDay = (int)(endOfDay.getTime() - startOfDay.getTime()); | |
if (businessTotalMillis > mSecInOneBusinessDay) { | |
log(((int)Math.floor(mSecInOneBusinessDay / mSecInOneHour)) + ""); | |
int endDay = ((int)Math.floor(mSecInOneBusinessDay / mSecInOneHour)); | |
log("End Day " + endDay + " hours"); | |
return endDay; | |
} | |
} | |
} | |
// otherwise, it must be a full working day | |
else { | |
int mSecInOneBusinessDay = (int)(endOfDay.getTime() - startOfDay.getTime()); | |
int fullDay = ((int)Math.floor(mSecInOneBusinessDay / mSecInOneHour)); | |
log("Full Day " + fullDay + " hours"); | |
return fullDay; | |
} | |
return 0; | |
} | |
/** | |
* Helper method to reset the time on a date to 00:00 or midnight. | |
* | |
* @param Date to reset time on. | |
* @return Adjusted date with time set to 00:00 | |
*/ | |
private static Date trimTimeOffDate(Date date) { | |
GregorianCalendar oneDate = new GregorianCalendar(); | |
oneDate.setTime(date); | |
oneDate.set(GregorianCalendar.HOUR_OF_DAY, 0); | |
return oneDate.getTime(); | |
} | |
/** | |
* Helper method to quit program if command was "quit" | |
* | |
* @param Command string to compare with "quit" | |
*/ | |
private static void checkForProgramQuit(String s) { | |
// check for a "quit" command | |
if (s.equalsIgnoreCase("quit") || | |
s.equalsIgnoreCase("q") || | |
s.equalsIgnoreCase("exit")) { | |
scan.close(); | |
System.exit(0); | |
} | |
// next, check for a "help" command, just in case | |
if (s.equalsIgnoreCase("?") || | |
s.equalsIgnoreCase("help") || | |
s.equalsIgnoreCase("command") || | |
s.equalsIgnoreCase("commands")) { | |
displayInstructions(); | |
} | |
} | |
/** | |
* Simple log helper. | |
* | |
* @param String to display if isLogging is true. | |
*/ | |
private static void log(String s) { | |
if (isLogging) display("Log: " + s); | |
} | |
/** | |
* Simple display helper. | |
* | |
* @param String to display to console. | |
*/ | |
private static void display(String s) { | |
System.out.println(s); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment