I am writing a program in Java, which basically find the number of days between 2 specific dates. The user inputs two dates in DD/MM/YYYY format, and I take the sub strings of the day/month/year and calculate the number of days between the 2. I also did a sort of validation, where if the format is wrong (for example d/mm/yyyy) then the person has to re-write the date in the right format. I did this by making sure that the / in the date are in their right position. If the 4 / match, then a boolean variable gives me true, and the program continues, if not it gives me false and it asks for the date again.
The problem is that it is always giving me false, and even then, it is not re-looping back.
import java.util.*;
public class DateDifference {
int day1, day2, month1, month2, year1, year2;
String startdate, enddate, day1S, day2S, month1S, month2S, year1S, year2S;
String datevalidation = "/";
boolean dval;
public static void main(String args[]){
DateDifference difference = new DateDifference();
}
DateDifference() {
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
Scanner sc = new Scanner (System.in);
do {
System.out.println("Enter Start Date [dd/mm/yyyy]:");
startdate = sc.next();
System.out.println("Enter End Date [dd/mm/yyyy]:");
enddate = sc.next();
int l1 = startdate.length();
int l2 = enddate.length();
day1S = startdate.substring(0,2);
month1S = startdate.substring(3,5);
year1S = startdate.substring(6,l1);
day2S = enddate.substring(0,2);
month2S = enddate.substring(3,5);
year2S = enddate.substring(6,l2);
if (startdate.substring(2,3).equals(datevalidation) & startdate.substring(5,6).equals(datevalidation) & enddate.substring(2,3).equals(datevalidation) & enddate.substring(5,6).equals(datevalidation))
dval = true;
else
dval = false;
System.out.println("Wrong date format. Try again");
} while (dval = false);
day1 = Integer.parseInt(day1S);
month1 = Integer.parseInt(month1S);
year1 = Integer.parseInt(year1S);
day2 = Integer.parseInt(day2S);
month2 = Integer.parseInt(month2S);
year2 = Integer.parseInt(year2S);
cal1.set(year1, month1 - 1, day1);
cal2.set(year2, month2 - 1,day2);
System.out.println("Days= "+daysBetween(cal1.getTime(),cal2.getTime()));
}
public int daysBetween(Date cal1, Date cal2){
return (int)( (cal2.getTime() - cal1.getTime()) / (1000 * 60 * 60 * 24));
}
}
Here are some images on how it is working:
When input is correct:
http://vvcap.net/db/2100RYdaSM1T6EXLqgq5.png
When input is not correct:
http://vvcap.net/db/9qSEwDKSTIdLAWmxS_Cy.png
When not correct, it just gets stuck when its trying to make 1/ in an integer, which I can understand.
Any help?
Thanks a lot.
You have a typo in this row
} while (dval = false);
operation dval = false is always false so your do .. while runs only once. I think you meant to use
} while (dval == false);
to have real loop.
To verify the loop behavior you can run this test and look what happens:
#Test
public void testLoop() {
int iteration = 0;
boolean flag;
do {
flag = false; // unused assignment
++iteration; // iteration counter
System.out.println( "Running iteration " + iteration );
} while ( flag = false );
System.out.println( "Loop finished. Total number of iterations is " + iteration );
}
Your problem, from what I see, is when you are taking the substring() of the dates. You are checking to see if the position equals "/" BUT you are taking 2 positions (hence the error showing that the string you are converting to and int is "1/" from the error code.
Try changing all the If statement line looks like the following:
From
if (startdate.substring(2,3).equals(datevalidation) & startdate.substr...
dval = true;
...
To
if ( !startdate.substring(2,3).contains(datevalidation) &
!startdate.substring(5,6).contains(datevalidation) &
!enddate.substring(2,3).contains(datevalidation) &
!enddate.substring(5,6).contains(datevalidation))
dval = true;
...
AND the while() statement should be == not just =. You're setting it rather than checking on each iteration of the loop.
Rather than checking if 2 characters equals 1 character (e.g. "1/".equals("/")) you are now checking to see if those 2 characters DO NOT contain the separator.
Also you want want a checker or a try-catch block just in-case the two digits entered are not numeric to stop the NumberFormatExcpetion from returning.
Hope this helps
Related
I have one question for my first development project in Java9.
I need to insert an Object with some info and a Date type, inside an ArrayList
only if the time is not present in the ArrayList and if it respects the condition that every time in the ArrayList must be stored every 10 minutes.
So, for example the idea is something like that:
correct: [21:10, 21:20, 21:50, 22:00],
incorrect: [21:05, 21:10, 21:20, 21:55, 22:00]
I try something like this:
private static ArrayList<Order> orders = new ArrayList<Order>();
//ordinazione = orderTime,name,surname,adderess,pizze;
public Pizzeria() {
Order ord = new Order(name, surname, address, num_pizze);
isValid(ord);
}
private void isValid(Order ord) {
boolean valid = false;
long prew,current;
long add = ord.getOrderTime().getTime();
int min10 = 10*60*1000; //10 minutes
if(orders.size() == 0) {
addOrder(ord);
}else if(orders.size() == 1){
current = orders.get(0).getOrderTime().getTime() / 1000;
if(add > current) {
if(add - current >= min10) {
valid = true;
addOrder(order);
}
}else{
if(current - add >= min10) {
valid = true;
addOrder(ord);
}
}
}else{
int i = 0;
while (orders.size() > i) {
prec = i > 1 ? orders.get(i-1).getOrderTime().getTime() / 1000 : 0;
current = orders.get(i).getOrderTime().getTime() / 1000;
if (current - add >= min10 && add - prec >= min10) {
valid = true;
addOrder(ord);
break;
}
i++;
}
}
if(!valid) {
System.out.println("this time is not allowed!");
}
}
public void addOrder(Orderd ord) {
orders.add(ord);
}
any advice?
It may not be the most beautiful solution, but it’s pretty simple: allocate an array with a slot for an order every 10 minutes of the day.
First we need the array of orders:
/** Accept an order every 10 minutes */
private static final int SLOT_SIZE_MINUTES = 10;
private Order[] orders
= new Order[Math.toIntExact(Duration.ofDays(1).toMinutes()) / SLOT_SIZE_MINUTES];
Now the method to fit a new order into the orders could be like:
/**
* If the order fits into a vacant slot that agrees with the time +/- 10 minutes,
* adds it there, adjusts the order time and returns true;
* otherwise returns false
*/
private boolean addOrderIfValid(Order newOrder) {
LocalTime orderTime = newOrder.getOrderTime();
int slotIndex = orderTime.get(ChronoField.MINUTE_OF_DAY) / SLOT_SIZE_MINUTES;
if (orders[slotIndex] != null) { // slot is already taken
slotIndex++;
if (slotIndex == orders.length) { // end of array
// start over from 00:00
slotIndex = 0;
}
}
if (orders[slotIndex] == null) { // vacant
newOrder.setOrderTime(LocalTime.MIN.with(ChronoField.MINUTE_OF_DAY, slotIndex * SLOT_SIZE_MINUTES));
orders[slotIndex] = newOrder;
return true;
} else { // did not find a vacant slot
return false;
}
}
What my method does: It tries to fit the order into the right 10 minutes slot based on the order time already in the order, truncating the time to a 10 minutes slot. If the slot is already taken, it looks into the following slot, using cyclic overflow. If either of the two slots tried is vacant, it sets the order time to the appropriate time for the slot found. This is also what ensures that the time will be at a whole 10 minutes of the hour: 21:00, 21:10, etc., not 21:05.
Link
Oracle tutorial: Date Time explaining how to use java.time.
A couple weeks new at coding! I've been assigned to make a method where the user will be able to book an 'appointment' between 9am to 5pm. I have made an boolean Array of size 8 named availability (0 = 9am, 1 = 10am, 2 = 11am, 3 = 12am ... 8 = 17pm.) True means the time is available, false means the time is not available.
The method has the params of description, hour and duration. My method IS able to book an appointment at a chosen time.
However, lets say, I booked an appointment at 9am with a duration of 1. --> 0 is now false.
Next, I booked an appointment at 11am with a duration of 1. --> 2 is now false.
I then book an appointment at 10am with a duration of 2. --> 1 (10am) should stay true, as a user shouldn't be able to book for 2 hours if the next hour (11am) is already booked, right?
I attempted to make this occur in my code, but to no avail. My code still books 10am and sets the slot to false! From what I've gathered, I believe the issue is line 96, the if statement checking if any of the slots during the duration are false.
What I've attempted is making a boolean variable set as true at the start of the code , and if the if statement finds a false availability, set the check variable as false. This stops the next block of code, where an IF statement checks if 'check' is true (if all the slots during the duration are true, as it wasn't set false).
public boolean makeAppointment(String desc, int duration, int hour) {
boolean check = true;
if (!((hour + (duration - 1) > 17))) { // it'll be 10
int booleanHour = hour - 9; // it'll be 1
if (booleanHour <= availability.length && booleanHour >= 0 && duration > 0 && duration <= 4) { // This 4 is a placeholder, subject to change.
for (int i = booleanHour; i < booleanHour + duration; i++) {
if (availability[i] == false) { // This isn't working? Confusion.
System.out.println( // response to if false
"This has hour been booked, please choose another time. We open at 9am, and close at 5pm.");
System.out.println(check);
check = false;
return false;
}
if (check) {
for (int b = booleanHour; b < booleanHour + duration; b++) {
availability[b] = false;
Appointment appoint = new Appointment(desc, duration, b + 9);
schedule.put(b + 9, appoint);
}
return true;
}
}
} else {
System.out.println("The max duration of a meeting is 4 hours.");
}
}
return false;
}
This is my test code as well.
Day day5 = new Day();
day5.makeAppointment("hello", 1, 9);
assertEquals(day5.getAvailability(0), false);
day5.makeAppointment("hello", 1, 11);
assertEquals(day5.getAvailability(2), false);
day5.makeAppointment("hello", 2, 10);
assertEquals(day5.getAvailability(1), true);
I have been trying to find the issue and fix it without seeking outside support, but it's come to the point where staring at a computer screen isn't a good way of learning, and having someone who can point out an issue which I can learn from is the best option!
If I do get a response, thank you! :) If anything about this post isn't what is allowed, sorry, first time!
You missed closing bracket and instead of looping over all days checking whether they are booked or not you are checking only the first one and then making appointment. It's working because 10 is obviously free - the program will not check 11 then, even if you would like to
for (int i = booleanHour; i < booleanHour + duration; i++) {
if (availability[i] == false) {
System.out.println("This has hour been booked, please choose another time. We open at 9am, and close at 5pm.");
System.out.println(check);
check = false;
return false;
} // this is the end of IF not FOR - only first element was checked!
if (check) { // yup it's true because 10 is free...
for (int b = booleanHour; b < booleanHour + duration; b++) {
availability[b] = false; // here we are making all hours booked no matter they are booked or not already
Appointment appoint = new Appointment(desc, duration, b + 9);
schedule.put(b + 9, appoint);
}
return true;
}
} // and finally this is the end of FOR but it's too late
Please notice also that if you are using return false you are not accessing code after return keyword anymore - your check condition makes no sense then
Fixed code could look like this:
public boolean makeAppointment(String desc, int duration, int hour) {
//...
for (int i = booleanHour; i < booleanHour + duration; i++) {
if (!availability[i]) {
System.out.println("This has hour been booked, please choose another time. We open at 9am, and close at 5pm.");
return false;
}
}
for (int b = booleanHour; b < booleanHour + duration; b++) {
availability[b] = false; // here we are making all hours booked no matter they are booked or not already
Appointment appoint = new Appointment(desc, duration, b + 9);
schedule.put(b + 9, appoint);
}
return true;
//...
}
I'm currently working on a HR system and it has an option for get 10 consecutive days (working days except weekends) of leave in its leave management module. Its a J2EE application.
All I want is to get 'N' number of consecutive weekdays from the given date
Does anybody knows how to achieve this problem?
P.S : I'm not using any 3rd party libraries like JodaTime..
Here is my controller's code for single day leave application. It has nothing to do with the consecutive days thing. but posting this here to prove that i'm doing something serious..
if (action.equals("applyLeave")) {
Leave l = new Leave();
int userid = Integer.parseInt(request.getParameter("userid"));
int leavetype = Integer.parseInt(request.getParameter("leavetype"));
String from = request.getParameter("from"); // from time
String to = request.getParameter("to"); // to time
double total = Double.parseDouble(request.getParameter("total")); // total hours
String r1 = request.getParameter("rep1");
String r2 = request.getParameter("rep2");
if (r1 == null || r1.isEmpty()) {
r1 = "0";
}
if (r2 == null || r2.isEmpty()) {
r2 = "0";
}
int rep1 = Integer.parseInt(r1);
int rep2 = Integer.parseInt(r2);
String reason = request.getParameter("reason");
String date = request.getParameter("date");
l.setUser(userid);
l.setLeavetype(leavetype);
l.setDate(date);
l.setFrom(from);
l.setReason(reason);
l.setRep1(rep1);
l.setRep2(rep2);
l.setTo(to);
l.setTotal(total);
dao.saveLeave(l);
// get manager of the department
UserDao udao = (UserDao) ctx.getBean("udao");
DepartmentDao ddao = (DepartmentDao) ctx.getBean("depdao");
NotificationDao notificationDao = (NotificationDao) ctx.getBean("notificationDao");
User u = udao.getUserByUserID(userid).get(0);
int department = u.getDepartment();
Department d = ddao.getDepartmentByID(department).get(0);
int manager = d.getManager();
// save a notification for the respective manager
// insert notification
String text = u.getFirstname() + " " + u.getLastname() + " has applied for a leave";
Notification n = new Notification();
n.setUserid(manager);
n.setFk(dao.getLeaveID());
n.setType(3);
n.setText(text);
notificationDao.saveNotification(n);
PrintWriter out = res.getWriter();
res.setContentType("text/html");
Gson gson = new Gson();
JsonObject myObj = new JsonObject();
myObj.add("message", gson.toJsonTree("Successfully Inserted"));
out.println(myObj.toString());
out.close();
}
List<Date> holidays = conf.getHolidays();
List<Date> nWorkingDays = new ArrayList<>();
// get the current date without the hours, minutes, seconds and millis
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
// iterate over the dates from now and check if each day is a business day
int businessDayCounter = 0
while (businessDayCounter < n) { //You want n working days
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY && !holidays.contains(cal.getTime())) {
businessDayCounter++;
nWorkingDays.add(cal.getTime());
}
cal.add(Calendar.DAY_OF_YEAR, 1);
}
return nWorkingDays;
Adapted from this answer: https://stackoverflow.com/a/15626124/1364747
Not sure whether you require the solution in standard java (tagged with javascript namely) but I guess you could do it as follows:
int numberOfDays = 10;
// Get current date
Calendar calendar = Calendar.getInstance();
//Repeat until all consecutive weekdays consumed
while(numberOfDays >0) {
int day = calendar.get(Calendar.DAY_OF_WEEK);
if((day != Calendar.SUNDAY) && (DAY != Calendar.SATURDAY)) {
numberOfDays--;
}
calendar.add(Calendar.DAY,1);
}
// Calendar now contains the date after consuming all
// consecutive week days
return calendar;
WARNING: Haven't compiled nor run this example so might cause exceptions.
Code:
Iterator<String> termIncomeKeys = termIncome.keySet().iterator();
while(termIncomeKeys.hasNext()){
String month = termIncomeKeys.next();
System.out.println(month);
}
The month is printed as
Jan(2012) - Jan(2012)
Feb(2012) - Mar(2012)
Apr(2012) - May(2012)
Jun(2012) - Jun(2012)
Jul(2012) - Oct(2012)
What I want to achieve is I want to print the duration in terms of months between each of the entries. That is, Duration between first entry is 1 month, duration between second is 2 and so on.
I do not know if there is a ready-made class that could parse these strings for you, but the logic is simple:
convert the three-letter months to numbers (e.g. 0-11), and convert the years to numbers as well.
The difference is <year-diff>*12 + <month-diff>, where <month-diff> might be negative.
Assuming Same Year:
enum Month{
JAN(0),
FEB(1),
MAR(2),
APR(3),
....
DEC(11);
Month(int index){this.index = index;}
int index;
int getIndex() {return index;}
}
Iterator<String> termIncomeKeys = termIncome.keySet().iterator();
while(termIncomeKeys.hasNext()){
String month = termIncomeKeys.next();
String str[] = month.split("-");
String m0 = str[0], m1 = str[1];
String y0 = mo.substr(m0.indexOf('(')+1, mo.lastIndexOf(')'));
String y1 = m1.substr(m1.indexOf('(')+1, m1.lastIndexOf(')'));
int yr0 = Integer.parseInt(yo), yr1 = Integer.parseInt(y1);
m0 = m0.substr(0, mo.indexOf('(')).trim().toUpperCase();
m1 = m1.substr(0, m1.indexOf('(')).trim(),toUpperCase();
int duration = yr1 *Month.valueOf(m1).getIndex() - yr0 *Month.valueOf(m0).getIndex();
}
I have a list of dates and prices:
Date Price
1/3/2000 10.00
1/5/2000 10.45
1/7/2000 10.25
... ...
I have a separate list of dates with all dates:
Date
1/1/2000
1/2/2000
1/3/2000
...
I need to have them combined so that the prior price is filled in for the dates that are missing prices:
Date Price
1/1/2000 10.00
1/2/2000 10.00
1/3/2000 10.00
1/4/2000 10.00
1/5/2000 10.45
1/6/2000 10.45
1/7/2000 10.25
... ...
I am currently trying to loop through array lists holding the data but can't line the dates up correctly, especially at the beginning and end. I am using Java/Mysql/JDBC right now but am open to R also. Thanks for any suggestions.
Thanks to everyone for your help. Here's what I ended up doing:
-I created a list of all indexes where the dates matched.
-I then inserted the prices into an array with the same number of elements as the full time list.
-I then created 3 loops, one for the elements before the first matching time, one for the elements after the last matching element and finally one for everything in between.
-These three filled in the prices that were missing.
Just though I'd share. Thanks for all your help.
public static void checkLengths(ArrayList<String> masterTimes, ArrayList<String> testTimes, ArrayList<Double> prices){
ArrayList<Double> temp = new ArrayList<Double>();
ArrayList<Integer> matches = new ArrayList<Integer>();
Double[] temp2 = new Double [masterTimes.size()];
int mt = masterTimes.size();
int tt = testTimes.size();
if(mt == tt){
return;
}else{
int mast = 0;
int test = 0;
String mt1 = masterTimes.get(0);
String tt1 = testTimes.get(0);
test = 0;
for(int i = 0; i < masterTimes.size(); i++){
mt1 = masterTimes.get(i);
tt1 = testTimes.get(test);
System.out.println(" | mt1: " + mt1 + " | tt1: " + tt1);
if(mt1.equals(tt1)){
matches.add(i);
System.out.println("Inserting: " + i);
if(test < testTimes.size()){
test++;
}
if(test == testTimes.size()){
break;
}
}
}
System.out.println("Matches:");
printAL(matches);
// puts in known prices.
for(int i = 0; i < matches.size(); i++){
int g = matches.get(i);
temp2[g] = prices.get(i);
}
System.out.println("FirstPrices:");
printAR(temp2);
// Finds index of first and last matching times.
int matcher1 = matches.get(0);
int ind = matches.size() - 1;
int matcher2 = matches.get(ind);
System.out.println("Matcher1:" + matcher1 + " | Matcher2: " + matcher2);
// If a price is empty/null, it puts the prior price in it.
for(int i = matcher1; i < matcher2; i ++){
System.out.println(i + " | " + temp2[i]);
if(temp2[i] == null){
System.out.println(temp2[i] + " | " + temp2[i-1]);
temp2[i] = temp2[i-1];
}
}
System.out.println("SecondPrices:");
printAR(temp2);
// Deals with start.
for(int i = matcher1; i >= 0; i--){
if(temp2[i] == null){
temp2[i] = temp2[i+1];
}
}
System.out.println("ThirdPrices:");
printAR(temp2);
// Deals with end.
for(int i = matcher2; i < temp2.length; i++){
if(temp2[i] == null){
temp2[i] = temp2[i-1];
}
}
System.out.println("FourthPrices:");
printAR(temp2);
prices.clear();
System.out.println("Final Check:");
for (int i = 0; i < masterTimes.size(); i++){
System.out.println(i + " | " + masterTimes.get(i) + " | " + temp2[i]);
}
}
}
It is difficult to help without looking at the code but it seems like your indexes are not matching up or something is wrong with your looping logic.
Consider using a HashTable or a HashMap using the date strings as keys and price as values.
Loop through your date range one day at a time look up the price in the HashTable, if not found then use the previous price.
This sort of problem does take a bit of doing to do correctly. Sometimes using a flow chart helps if you get stuck.
Try using the following sample code:
import java.sql.*;
import java.util.*;
public class FillDates
{
public static void fillUnknownDates(Connection c) throws SQLException
{
// Loads in a Vector of Strings of all the dates
Statement state = c.createStatement();
ResultSet results = state.executeQuery("SELECT d FROM Dates ORDER BY d;");
Vector<String> dates = new Vector<String>();
while (results.next())
{
dates.add(results.getString("d"));
}
// Load in a list of all date/price combinations
Vector<DatePrice> pairs = new Vector<DatePrice>();
state = c.createStatement();
results = state.executeQuery("SELECT d, p FROM DatePrices ORDER BY d;");
while (results.next())
{
pairs.add(new DatePrice(results.getString("d"), results.getString("p")));
}
// Now go through the two lists and add missing prices
state = c.createStatement();
int dateIndex = 0;
DatePrice last = pairs.get(0), current;
for (int pairIndex = 1; pairIndex < pairs.size(); pairIndex++)
{
current = pairs.get(pairIndex);
while (dateIndex < dates.size() && dates.get(dateIndex).compareTo(current.getDate()) < 0)
{
// Batch things up so it takes less time to run
state.addBatch("INSERT INTO DatePrices VALUES (\""+dates.get(dateIndex)+"\", \""+current.getPrice+"\");");
dateIndex ++;
}
last = current;
}
state.executeBatch();
}
// A convenience class
public static class DatePrice
{
private String date, price;
public DatePrice(String date, String price)
{
this.date = date;
this.price = price;
}
public String getDate()
{
return date;
}
public String getPrice()
{
return price;
}
}
}
Note that it's not complete, and you'll need to change the names of your tables and columns before trying it out.
Okay... I just shooting at it while being on the fon :)
In MySQL, let's assume you got two tables, dates_prices and all_dates. Then LEFT JOIN them on dates and order them by date.
If you use R and MySQL you can use the RMySQL package to load the resulting table to R.
In R you can convert the dates to POSIX with as.POSIXlt. You also might want to use the lagfunction in R (but I am not sure yet if that helps with lags of varying spans).
Apart from that you could use R's ´sqldf` package if you want to try with "plain" R but want to use SQL functionality. If you post some reproducible code to set up the data.. I could try to the give something more concrete back.
EDIT:
The impute package might be what you really looking for... see also here
Here is an R solution.
Uncomment the two install.packages lines if you don't have those packages already installed. Also textConnection(Lines1) and textConnection(Lines2) are just to keep the example self contained and in reality would be replaced with something like "myfile1.dat" and "myfile2.dat" assuming the data is in those files.
It reads in the data creating zoo object z and a Date vector dt. It then merges z with a zero width zoo object (i.e. it has dates but no data) whose date index is made from dt. na.locf (last observation carried forward) fills out the missing values in reverse order since fromLast = TRUE
Lines1 <- "Date Price
1/3/2000 10.00
1/5/2000 10.45
1/7/2000 10.25"
Lines2 <- "Date
1/1/2000
1/2/2000
1/3/2000"
# install.packages("zoo")
# install.packages("chron")
library(zoo)
library(chron)
z <- read.zoo(textConnection(Lines1), header = TRUE, FUN = as.chron)
dt <- as.chron(scan(textConnection(Lines2), skip = 1, what = ""))
na.locf(merge(z, zoo(, dt)), fromLast = TRUE)
The result is:
> na.locf(merge(z, zoo(, dt)), fromLast = TRUE)
01/01/00 01/02/00 01/03/00 01/05/00 01/07/00
10.00 10.00 10.00 10.45 10.25
There are three vignettes (PDF documents) that come with the zoo package and R News 4/1 Help Desk article has info and references on dates.