First off, I'm using the library https://github.com/alamkanak/Android-Week-View
I have an API returning data for one week at a time.
For example GET /stuff/{current_week_number}
Then a scroll listener set up that checks if the week has changed, and will then load
GET /stuff/{new_week_number}
The problem is that all events will be in the current week position as duplicates. I know the library wants events on a per month basis, is it the problem?
Been debugging this for a day now, help would be greatly appreciated.
Function for creating the event:
private WeekViewEvent createNew(JSONObject json, int week) {
String eventTitle = "";
String colorString = "#999";
String startTimeString = "";
String endTimeString = "";
int dayOfWeek = 0;
try {
eventTitle = json.getString("text").replaceAll("\n", " ");
colorString = json.getString("color");
startTimeString = json.getString("startTime");
endTimeString = json.getString("endTime");
dayOfWeek = json.getInt("day");
} catch (JSONException e) {
e.printStackTrace();
}
Calendar startTime = Calendar.getInstance();
startTime.set(Calendar.HOUR_OF_DAY, hoursFromString(startTimeString));
startTime.set(Calendar.MINUTE, minutesFromString(startTimeString));
startTime.set(Calendar.WEEK_OF_YEAR, week);
startTime.set(Calendar.DAY_OF_WEEK, dayOfWeek);
Calendar endTime = (Calendar) startTime.clone();
endTime.set(Calendar.HOUR_OF_DAY, hoursFromString(endTimeString));
endTime.set(Calendar.MINUTE, minutesFromString(endTimeString));
WeekViewEvent event = new WeekViewEvent(mGlobalCounter, eventTitle, startTimeString + " - " + endTimeString, startTime, endTime);
event.setColor(Color.parseColor(colorString));
if (event.getColor() == Color.WHITE) {
event.setColor(R.color.event_color_01);
}
return event;
}
Month change listener + helper method (from example)
private boolean eventMatches(WeekViewEvent event, int year, int month) {
return (event.getStartTime().get(Calendar.YEAR) == year && event.getStartTime().get(Calendar.MONTH) == month - 1) || (event.getEndTime().get(Calendar.YEAR) == year && event.getEndTime().get(Calendar.MONTH) == month - 1);
}
MonthLoader.MonthChangeListener mMonthChangeListener = new MonthLoader.MonthChangeListener() {
#Override
public List<WeekViewEvent> onMonthChange(int newYear, int newMonth) {
// Populate the week view with some events.
List<WeekViewEvent> events = new ArrayList<>(); //getEvents(newYear, newMonth);
for (WeekViewEvent event : mNewEvents) {
if (eventMatches(event, newYear, newMonth)) {
events.add(event);
}
}
mFetchedWeeks.add(Integer.valueOf(mWeek));
return events;
}
};
And here's the JSON-response from the API
https://gist.github.com/jonathanort/668de267966e3b673fffe23dfbdfb90b
Also, my modified version of WeekView.java
https://gist.github.com/jonathanort/472d86355dcdbc338f13373a838f548a
The solution was to add the line
startTime.get(Calendar.DAY_OF_WEEK);
before
startTime.set(Calendar.DAY_OF_WEEK, dayOfWeek);
Apparently it will not set the day otherwise
Related
I have a project where i am creating shifts. Users can request days off so when im creating a shift i want to check if that user has requested that day off. I have used for and if statements to do this but it seems very messy and it doesn't always work. Is there a simpler way to do this?
This is my code for creating a shift.
Shift createShift(#RequestBody ShiftParams params)
{
User u = userService.findByFirstName(params.text);
Set<User> userSets = new HashSet<>();
userSets.add(u);
List<Request> req = u.getRequests();
if(req != null && req.isEmpty()) //This creates the shift if
the user has no requests
{
Shift shift = new Shift();
shift.setStart(params.start);
shift.setEnd(params.end);
shift.setUsersShifts(userSets);
shiftService.save(shift);
}
else
{
for(Iterator<Request> it= req.iterator(); it.hasNext();)
{
Request empReq = it.next();
if(empReq.getStatus() == Status.Accepted)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //for string
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); //for localdate
//Request start date in LocalDate
Date d = empReq.getDate();
String rDateStart = sdf.format(d);
LocalDate reqStartDate = LocalDate.parse(rDateStart, formatter).minusDays(1);
System.out.println("Req start date is " + reqStartDate);
//Request end date in LocalDate
int numDays = empReq.getNumDays();
LocalDate endDateReq = reqStartDate.plusDays(numDays).plusDays(1);
System.out.println("Request finish date is" + endDateReq);
//Shift start date in LocalDate
String shiftDate = (params.start).format(formatter);
LocalDate formatDateTime = LocalDate.parse(shiftDate, formatter);
System.out.println("Shift date in date format " + formatDateTime);
if(formatDateTime.isAfter(reqStartDate) &&
formatDateTime.isBefore(endDateReq)) //checks is the user has requested day off
{
System.out.println("The employee has requested that day off");
} else { // if they havent requested that day off the shift is created
Shift shift = new Shift();
shift.setStart(params.start);
shift.setEnd(params.end);
shift.setUsersShifts(userSets);
shiftService.save(shift);
}
}
}
return null;
}
Assumption: params.start is java.util.Date type
public Shift createShift(final #RequestBody ShiftParams params) {
User u = userService.findByFirstName(params.text);
Set<User> userSets = Collections.singleton(u);
List<Request> requests = u.getRequests();
if ( requests == null || requests.isEmpty() || hasNoDayOffOnShiftDate(requests, params)) //This creates the shift if the user has no requests
{
Shift shift = buildShift(params, userSets);
shiftService.save(shift);
return shift;
}
return null;
}
private boolean hasNoDayOffOnShiftDate(List<Request> requests, ShiftParams params) {
final LocalDate shiftStartDate = convertToLocalDate(params.start);
Optional<Request> request = requests
.stream()
.filter(req -> req.getStatus() == Status.Accepted)
.filter(req -> isDayOffOnShiftDate(req, shiftStartDate))
.findAny();
return request.isEmpty();
}
private boolean isDayOffOnShiftDate(Request empReq, LocalDate shiftStartDate) {
//Request start date in LocalDate
LocalDate reqStartDate = convertToLocalDate(empReq.getDate()).minusDays(1);
System.out.println("Req start date is " + reqStartDate);
//Request end date in LocalDate
int numDays = empReq.getNumDays();
LocalDate endDateReq = reqStartDate.plusDays(numDays).plusDays(1);
System.out.println("Request finish date is" + endDateReq);
if (shiftStartDate.isAfter(reqStartDate) &&
shiftStartDate.isBefore(endDateReq)) //checks is the user has requested day off
{
System.out.println("The employee has requested that day off");
return true;
}else {
return false;
}
}
private Shift buildShift(#RequestBody ShiftParams params, Set<User> userSets) {
Shift shift = new Shift();
shift.setStart(params.start);
shift.setEnd(params.end);
shift.setUsersShifts(userSets);
return shift;
}
public LocalDate convertToLocalDate(Date dateToConvert) {
return LocalDate.ofInstant(
dateToConvert.toInstant(), ZoneId.systemDefault());
}
I want to make an offline daily gift system. How can I do it.
date = new Date();
calendarG = new GregorianCalendar();
calendarG.setTime(date);
if(!prefs.contains("lastloginday"))
prefs.putInteger("lastloginday", calendarG.get(Calendar.DAY_OF_MONTH));
if (calendarG.get(Calendar.DAY_OF_MONTH) - 1 == prefs.getInteger("lastloginday")) {
prefs.putInteger("lastloginday", calendarG.get(Calendar.DAY_OF_MONTH));
prefs.putInteger("dailyCombo", prefs.getInteger("dailyCombo") + 1);
prefs.putInteger("Coin", prefs.getInteger("Coin") + prefs.getInteger("dailyCombo") * 25);
}else{
prefs.putInteger("lastloginday", calendarG.get(Calendar.DAY_OF_MONTH));
}
This code is not useful in different months.
You can do in this way :
Preferences preferences=Gdx.app.getPreferences("MyPref");
String LAST_LOGIN_DAY="lastloginday";
GregorianCalendar calendarG = new GregorianCalendar();
calendarG.setTime(new Date());
if(!preferences.contains(LAST_LOGIN_DAY)) {
//first day in App
preferences.putInteger(LAST_LOGIN_DAY, calendarG.get(Calendar.DAY_OF_YEAR));
preferences.flush();
}
if(preferences.getInteger(LAST_LOGIN_DAY)-1==calendarG.get(Calendar.DAY_OF_YEAR)){
//next loginday up to a year
updateValue(preferences,calendarG);
}else{
if(calendarG.get(Calendar.DAY_OF_YEAR)==1) {
// check for the 1st day of the year
boolean isLeap = calendarG.isLeapYear(calendarG.get(Calendar.YEAR));
if (isLeap && preferences.getInteger(LAST_LOGIN_DAY)==366 ) {
updateValue(preferences,calendarG);
}else if(preferences.getInteger(LAST_LOGIN_DAY)==365){
updateValue(preferences,calendarG);
}
else
preferences.putInteger(LAST_LOGIN_DAY,calendarG.get(Calendar.DAY_OF_YEAR));
}
else
preferences.putInteger(LAST_LOGIN_DAY,calendarG.get(Calendar.DAY_OF_YEAR));
}
Here is update method :
public void updateValue(Preferences preferences,GregorianCalendar calendarG){
preferences.putInteger(LAST_LOGIN_DAY,calendarG.get(Calendar.DAY_OF_YEAR));
preferences.putInteger("dailyCombo", preferences.getInteger("dailyCombo",0) + 1);
preferences.putInteger("Coin", preferences.getInteger("Coin",0) + preferences.getInteger("dailyCombo",0) * 25);
preferences.flush();
}
I am trying to create a spinner that has hours and minutes. The minutes part needs to increment by 10 mins only and the time must range from the current time to an end time. I also need the minimum value (previously current time) to update to current time.
I tried playing around with it, but I just couldn't get it to work.
JSpinner spinner1 = new javax.swing.JSpinner();
SpinnerDateModel spinnermodel = new SpinnerDateModel();
spinnermodel.setCalendarField(Calendar.MINUTE);
spinner1.setModel(spinnermodel);
spinner1.setEditor(new JSpinner.DateEditor(spinner1, "hh:mm"));
SpinnerModel model = new SpinnerDateModel(currentDate, currentDate, latestDate, Calendar.MINUTE * 10 ?);
The SpinnerDateModel just uses 1 to increment the field you want to change.
I extended the SpinnerDateModel to add an addition property to the model to control the increment value instead of hard coding to 1:
import java.util.*;
import javax.swing.*;
public class MySpinnerDateModel extends SpinnerDateModel
{
private int increment = 1;
public MySpinnerDateModel(Date value, Comparable start, Comparable end, int calendarField)
{
super(value, start, end, calendarField);
}
public MySpinnerDateModel()
{
this(new Date(), null, null, Calendar.DAY_OF_MONTH);
}
public void setIncrement(int increment)
{
this.increment = increment;
}
public int getIncrement()
{
return increment;
}
#Override
public Object getNextValue()
{
Calendar cal = Calendar.getInstance();
Date value = (Date)getValue();
cal.setTime(value);
cal.add(getCalendarField(), increment);
Date next = cal.getTime();
Comparable end = getEnd();
return ((end == null) || (end.compareTo(next) >= 0)) ? next : null;
}
#Override
public Object getPreviousValue()
{
Calendar cal = Calendar.getInstance();
Date value = (Date)getValue();
cal.setTime(value);
cal.add(getCalendarField(), -increment);
Date prev = cal.getTime();
Comparable start = getStart();
return ((start == null) || (start.compareTo(prev) <= 0)) ? prev : null;
}
}
You should be able to use the model the way you did before but with one additional statement:
MySpinnerDateModel model = new MySpinnerDateModel(currentDate, currentDate, latestDate, Calendar.MINUTE);
model.setIncrement( 10 );
You can extend the SpinnerDateModel to specify the behavior. Below is an example in which the getNextValue and getPreviousValue are overridden to return values +/- 10 minutes:
Date now = new Date();
Date start = now;
final long tenMinutesInMillis = 1000 * 60 * 10;
Date end = new Date(now.getTime() + tenMinutesInMillis * 60);
SpinnerModel model = new SpinnerDateModel(now, start, end, Calendar.MINUTE){
#Override
public Object getNextValue(){
Date newDate = new Date(getDate().getTime() + tenMinutesInMillis);
Date endDate = (Date)getEnd();
return newDate.getTime() > endDate.getTime() ? endDate : newDate;
}
#Override
public Object getPreviousValue(){
Date newDate = new Date(getDate().getTime() - tenMinutesInMillis);
Date startDate = (Date)getStart();
return newDate.getTime() < startDate.getTime() ? startDate : newDate;
}
};
I have to do a validation in Date field which must be 18 years less than current date else it must show error.
public static boolean dobdateValidate(String date) {
boolean result = false;
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy");
try {
Date parseddate = sdf.parse(date);
Calendar c2 = Calendar.getInstance();
c2.add(Calendar.DAY_OF_YEAR, -18);
Date dateObj2 = new Date(System.currentTimeMillis());
if (parseddate.before(c2.getTime())) {
result = true;
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
you can use this method to get age
/**
* calculates age from birth date
*
* #param selectedMilli
*/
private void getAge(long selectedMilli) {
Date dateOfBirth = new Date(selectedMilli);
Calendar dob = Calendar.getInstance();
dob.setTime(dateOfBirth);
Calendar today = Calendar.getInstance();
int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR);
if (today.get(Calendar.MONTH) < dob.get(Calendar.MONTH)) {
age--;
} else if (today.get(Calendar.MONTH) == dob.get(Calendar.MONTH)
&& today.get(Calendar.DAY_OF_MONTH) < dob
.get(Calendar.DAY_OF_MONTH)) {
age--;
}
if (age < 18) {
//do something
} else {
}
str_age = age + "";
Log.d("", getClass().getSimpleName() + ": Age in year= " + age);
}
The core issue is that Calendar.DAY_OF_YEAR is not correct as "[DAY_OF_YEAR indicates] the day number within the current year".
Use Calendar.YEAR instead.
Other suggestions:
The dateObj2 variable is never used and should be removed.
Return directly instead of using an intermediate flag variable.
Take in a Date/Calendar object and leave the caller responsible for parsing.
I have two datetime values and i dont knw how to compare them. I know if i had only date values then before() and after() methods would have worked but i have no idea about Datetime values. All i have done is below plz tell me if its correct ?? and plz do guide me if its not a good way and a better alternative is available.
Date now = new Date();
DateTime currenttime = new DateTime(now, TimeZone.getTimeZone("IST"));
DateTime edate = e.getEnd().getDateTime();
if(currenttime.getValue()>edate.getValue())
{
//here I want to do the logic to delete this event.
}
e refers to the event object that is of google calendar. All i want to do here is check if Event e is past todays date and time. and if it is then i wanna delete the event.
You can use jdk Calendar to get and check days:
public boolean isDatePass(Date date) {
Calendar calendar = Calendar.getInstance();
// Getting day of year and year of checked date:
calendar.setTime(date);
int checkedYear = calendar.get(Calendar.YEAR);
int checkedDay = calendar.get(Calendar.DAY_OF_YEAR);
// Getting day of year and year of current date:
calendar.setTime(new Date());
int currentYear = calendar.get(Calendar.YEAR);
int currentDay = calendar.get(Calendar.DAY_OF_YEAR);
if(checkedYear != currentYear) {
return checkedYear < currentYear;
}
return checkedDay < currentDay;
}
For yoda DateTime:
public boolean isDatePass(DateTime date) {
// Getting day of year and year of checked date:
int checkedYear = date.getYear();
int checkedDay = date.getDayOfYear();
// Getting day of year and year of current date:
DateTime currentTime = new DateTime(now, TimeZone.getTimeZone("IST"));
int currentYear = currentTime.getYear();
int currentDay = currentTime.getDayOfYear();
if(checkedYear != currentYear) {
return checkedYear < currentYear;
}
return checkedDay < currentDay;
}
Not days only but time:
public boolean isDatePass(DateTime date) {
DateTime currentTime = new DateTime(now, TimeZone.getTimeZone("IST"));
return date.isAfter(currentTime);
}
More simple solution (according to javadoc when pass null to isAfter/isBefore this mean current or now):
public boolean isDatePass(DateTime date) {
return date.isAfter(null); // but it does not take in account time zone
}
public String deleteEvents() throws ParseException {
try {
boolean evtDelMsg = false;
int iEvtCnt = 0;
int totalEvents = lstEvents.size();
System.out.println("events are :"+lstEvents.getItems().toString());
if(lstEvents.size()>0)
{
for(Event e : lstEvents.getItems())
{
System.out.println("startdate is "+e.getStart().toString());
Date now = new Date();
try
{
if((new Date()).getTime() < e.getEnd().getDateTime().getValue())
{
evtDelMsg = EventManager.deleteEvent(getGoogleCalObj(), selectedCalId, e.getId());
iEvtCnt++;
}
}
catch(NullPointerException npe)
{
System.out.println("edate is null so creating");
processImportedEventsData();
}
}
}
else
{
System.out.println("no events in this calendar");
}
setInfoMsg("Successfully deleted " + iEvtCnt + " Events out of total " + totalEvents);
createEventFlag = true;
processImportedEventsData();
}
catch (IOException ex)
{
Logger.getLogger(ManageCalendar.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
This one worked for me I simply used the long value of the event's i.e "e" date and time and compared with the todays date time.The getValue() method returns in long which is milliseconds. This made it a bit simple.
And then in the loop i deleted all the events calling deleteEvent() of EventManager.