CalendarArray get dates betweeen two Dates and skip a few - java

i am trying to create an Array of Calendar Objects where i get all dates between start and end, while skipping the date "skip". So let's imagine i have the dates:
start = 04.03.2016
skip = 21.07.2016
end = 02.03.2017
i tried something like this, but it didn't work that well:
public static Calendar[] getRange(Calendar start, Calendar skip, Calendar end){
Calendar[] daysRange = new Calendar[100];
Calendar placeholder = Calendar.getInstance();
while(start.before(end)){
if(placeholder.getTime() == skip.getTime()){
continue;
} placeholder.add(Calendar.Date, 1);
}
//(pseudocode)
//add placeholder to daysRange
return daysRange;
}
I would appreciate any tips on how i could continue.
Thanks!

First:
while (start.before(end)) {
You never modify start or end, so the loop is endless.
Second: you use one placeholder object, that means that your whole array points to that one object, create a new Calendar for every step en the loop.
Third: don't use an array, use an ArrayList.

Related

How to RESET Arraylist at the end of the week?

I have an arraylist:
ArrayList<String> wholeWeekArrayList = new ArrayList<>();
DatabaseHelper(SQLite) is storing the values into the(above) arrayList:
Cursor data = mDatabaseHelper.getData();
while (data.moveToNext() ) {
wholeWeekArrayListString.add(data.getString(1));
//getString(1) is column values from SQLite
}
Then I have SumofWeek where all the data in wholeWeekArrayListString is added together.
(I Convert wholeWeekArrayListString to double to view it in a TEXTVIEW);
I want this SumOfWeek to reset to Zero at the end of the week but the data inside the SQLite must keep adding(for SumOfMonth view).
So by Sunday the data may be $50.00 (for Example) and Starting on int Monday. the data must reset to 0.0 and sum all the way up until Sunday.
This must happen weekly.
How would u do this? I have tried assining days of weeks.
Monday =1;
Tuesday = 2;
Wednesday =3;
// ...
and iterate through the whole week but Im not able to get(i), which is the data of each single day of the week and then reset it on which is
int Sunday =7;
I have the total amount but dont know what method to use to reset the data at the end of the week?
Without changing the DB calls, you´ll have to store the timestamp of the latest reset (resetTimestamp in the example below). If the current time is in a different week, the code will trigger a reset of sumofWeek. After that, it´s your normal sumofWeek logic.
Thread safety: to be added depending on the application specifics.
private ArrayList<Long> sumofWeek = new ArrayList<>();
private Long resetTimestamp;
public void populateWeek() {
if(resetTimestamp == null || isDifferentWeek(resetTimestamp)) {
sumofWeek = new ArrayList<Long>();
for(int i = 0; i < 7; i++){
sumofWeek.add(0l);
}
System.out.println(sumofWeek);
resetTimestamp = java.lang.System.currentTimeMillis();
}
// populate sumofWeek here
}
private boolean isDifferentWeek(long resetTimestamp) {
Calendar cl1 = new GregorianCalendar();
cl1.setTimeInMillis(java.lang.System.currentTimeMillis());
Calendar cl2 = new GregorianCalendar();
cl2.setTimeInMillis(resetTimestamp);
return cl1.get(Calendar.WEEK_OF_YEAR) != cl2.get(Calendar.WEEK_OF_YEAR);
}

Passing a string array in a main method

I have homework where I have to write a small program that asks for a number and returns the month assigned to that number.
So far I have written two different classes, one to prompt the user for int, and the other with the arrays of month. Now my problem is to pass over the months to the main class when the user enters a number.
So far for the main class I have this and I have no idea on how to proceed...
I get:
java:17: error: array required, but Date found System.out.println(monthName[index]);
I tried to be as detailed as possible.
import java.util.Scanner;
public class Driver {
public static void main(String[] args)
{
Utility input = new Utility();
final int MONTH_NAMES = 12;
int[] month = new int[MONTH_NAMES];
Date monthName = new Date();
{
System.out.println(input.queryForInt("Enter the number for a month ")) ;
}
for (int index = 0; index < 12; index++)
System.out.println(monthName[index]);
}
}
Your System.out line is not referencing the array you named month.
I don't think you intended to use Date monthName here
System.out.println(monthName[index]);
Judging by the number of indexes your for loop is counting, it looks like you wanted to use int[] month.
System.out.println(month[index]);
mouthName is a Date object, not an array. Also, why use a for loop to print out a whole year's mouth?
I think it can change the last for loop to System.out.printLn(mouthName.getMouth()) if the input.queryForIntmethod can successfully pass the int mouth to the mouthName object.

Most efficient way of checking if Date object and Calendar object are in the same month

I am working on a project that will run many thousands of comparisons between dates to see if they are in the same month, and I am wondering what the most efficient way of doing it would be.
This isn't exactly what my code looks like, but here's the gist:
List<Date> dates = getABunchOfDates();
Calendar month = Calendar.getInstance();
for(int i = 0; i < numMonths; i++)
{
for(Date date : dates)
{
if(sameMonth(month, date)
.. doSomething
}
month.add(Calendar.MONTH, -1);
}
Creating a new Calendar object for every date seems like a pretty hefty overhead when this comparison will happen thousands of times, soI kind of want to cheat a bit and use the deprecated method Date.getMonth() and Date.getYear()
public static boolean sameMonth(Calendar month, Date date)
{
return month.get(Calendar.YEAR) == date.getYear() && month.get(Calendar.MONTH) == date.getMonth();
}
I'm pretty close to just using this method, since it seems to be the fastest, but is there a faster way? And is this a foolish way, since the Date methods are deprecated? Note: This project will always run with Java 7
I can't comment on whether to use the deprecated methods, but if you choose not to there's no need to instantiate a new Calendar for every Date you check. Just use one other Calendar and call setTime(date) before the check (or one Calendar for every thread if you parallelize it).
As a side note, I do have to agree with ChristopheD's comment that this is something worthy of a database.
I think you can define a static DateFormat to extract the month and year from Date and use both objects as date only.
public static DateFormat formatter= new SimpleDateForm("MMyyyy");
public static boolean sameMonth(Date date1, Date date2)
{
return formatter.format(date1).equals(formatter.format(date2));
}

How to determine if the specific time is between given range?

Problem: I have a list containg hours, for example:
08:15:00
08:45:00
09:00:00
12:00:00
...
application is allowing user to make an appointment for a specific hour let'say: 8:15:00, each meeting takes half an hour.
Question: How to determine if there is a slot needed for appointment like this? I know that Calendar class have methods before() nad after(), but it doesn'solve my problem. I mean if there is appointment at 12:00 and another one at 12:00, how to prevent before making another one at 12:15?
edit:
I've tried using methods I mentioned before, like:
Calendar cal1 = Calendar.getInstance(); // for example 12:00:00
Calendar cal2 = Calendar.getInstance(); // for exmaple 12:30:00
Calendar userTime = Calendar.getInstance(); // time to test: 12:15:00
if(user.after(cal1)&& user.before(cal2)){
... // do sth
}
Check if the date to check is between the two provided:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm");
Date before = sdf.parse("07/05/2012 08:00");
Date after = sdf.parse("07/05/2012 08:30");
Date toCheck = sdf.parse("07/05/2012 08:15");
//is toCheck between the two?
boolean isAvailable = (before.getTime() < toCheck.getTime()) && after.getTime() > toCheck.getTime();
To book for a determinate hour, I would do a class with two dates and a method to check this:
public class Appointment{
private Date start;
private Date end;
public boolean isBetween(Date toCheck){....}
}
Then you can simply do an Schedule class extending ArrayList, adding a method isDateAvailable(Date toCheck), iterating the list of Appointments and checking that there is no one conflicting.
I'd have some kind of appointment class with either a start timestamp and a duration or a start time and an end time. Then when adding new appointments to the schedule, check that the appointment with the start time before the new appointment doesn't run over the start time of the proposed new appointment.
Well how you would do it specifically depends on how you are storing your data, format, etc., but generally what you would do is simply check if there is an appointment for any time between the requested time to the requested time + requested length.
// Example (using int time(1 = 1 minute), assuming that appointments can only be at 15min intervals)
boolean isHalfHourTimeSlotAvaliable(int time) {
for (int i = 0; i < appointments.size(); i++) {
if (appointments.get(i).time == time || appointments.get(i).time == time + 15) {
return false;
}
}
return true;
}

Grouping objects by date: am I an idiot?

I have a list of objects called Activity:
class Activity {
public Date activityDate;
public double amount;
}
I want to iterate through List, group them by date and return a new list . Here's what I currently do:
private List<Activity> groupToList(List<Activity> activityList) {
SimpleDateFormatter sdf = new SimpleDateFormatter("YYYY-MM-DD");
Map<String,Activity> groupMap = new HashMap<String,Activity>();
for (Activity a in activityList) {
String key = sdf.format(a.getActivityDate());
Activity group = groupMap.get(key);
if (group == null) {
group = new Activity();
groupMap.add(key, group);
}
group.setAmount(group.getAmount() + a.getAmount());
}
return new ArrayList<Activity>(groupMap.values());
}
Is it a WTF to use the DateFormatter in this way?
I'm using the DateFormatter because each activityDate could have time information.
I would just use the date object itself as the key. If it it bothers you because the date object is mutable, then use its toString() value. No reason to go making formats.
If the issue is that you want to normalize the date by removing the time component, it would be much better to do that withing the Activity object and remove the time component. If the issue is still further that there are potential time zone issues, I would use JodaTime, but there is no object in the JDK currently that represents a pure date without time, so going with a string isn't outrageous, but it should be hidden behind a method in the Activity object and the fact that it is a date formatted string without a time component should be an implementation detail.
java.util.Date is a quite poor abstraction for your need; it is IMO fair to stick to strings if nothing better is around, HOWEVER Joda-time provides a good datatype for you: DateMidnight or alternatively LocalDate if Activity is strictly timezome-independant.
other than that, the code looks good to me, you might be able to shorten it a bit using an implementation of Multimap, to avoid messy null-checking code. to be honest, it doesn't get much shorter than your solution:
public List<Activity> groupedByDate(List<Activity> input) {
//group by day
final Multimap<DateMidnight, Activity> activityByDay
= Multimaps.index(input, new Function<Activity, DateMidnight>() {
#Override
public DateMidnight apply(Activity from) {
return new DateMidnight(from.activityDate);
}
});
//for each day, sum up amount
List<Activity> ret = Lists.newArrayList();
for (DateMidnight day : activityByDay.keySet()) {
Activity ins = new Activity();
ins.activityDate = day.toDate();
for (Activity activity : activityByDay.get(day)) {
ins.amount+=activity.amount;
}
}
return ret;
}
Why not simply create a HashMap<Date, Activity>() instead of the roundabout way with Strings?
Sorry, I didn't answer the question. The answer is: yes, unless I am an idiot ;)
You could do this using the Date as the key if you used a TreeMap and provided a Comparator that only compared the year, month and day and not the time.
As already mentioned the best solution is to represent your date with day precission. If this is not possible joda is nice library.
If you can ignore daylight saving time then grouping by date can be accomplished much easier. A unix time day is 86 400 s long. The timestamp does ignore leap seconds. (Your timer stops for one second or the leap second is distributed in some way.) All date values were day is equal are the same day:
int msPerDay = 86400 * 1000;
long day = new Date().getTime() / msPerDay
One minor point is to adjust the timezone. For my timezone CET (UTC/GMT +1 hour) the GMT day starts one our later:
new GregorianCalendar(2009, 10, 1, 1, 0).getTime().getTime() / msPerDay) ==
new GregorianCalendar(2009, 10, 2, 0, 59).getTime().getTime() / msPerDay) ==
new Date().getTime() / msPerDay
If the daylight saving time is significant the best way is to use joda. The rules are just to complicated and locale specific to implement.

Categories

Resources