I'm trying to compare two instances of calendar but something does not work as I expect it. My code goes as following:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar now = Calendar.getInstance();
Calendar past = Calendar.getInstance();
past.set(2014,2,30);
Log.d("ppp",String.valueOf(now.after(past)) +" \n Past: " + past.toString() +" \n Now: "+ now.toString());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
I would expect the above code to return true, but looking at the logCat this is what I get:
false
Past: java.util.GregorianCalendar[time=1396174280322,areFieldsSet=true,lenient=true,zone=Europe/Amsterdam,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2014,MONTH=2,WEEK_OF_YEAR=14,WEEK_OF_MONTH=6,DAY_OF_MONTH=30,DAY_OF_YEAR=89,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=0,HOUR_OF_DAY=12,MINUTE=11,SECOND=20,MILLISECOND=322,ZONE_OFFSET=3600000,DST_OFFSET=3600000]
Now: java.util.GregorianCalendar[time=1394622680322,areFieldsSet=true,lenient=true,zone=Europe/Amsterdam,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2014,MONTH=2,WEEK_OF_YEAR=11,WEEK_OF_MONTH=3,DAY_OF_MONTH=12,DAY_OF_YEAR=71,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=0,HOUR_OF_DAY=12,MINUTE=11,SECOND=20,MILLISECOND=322,ZONE_OFFSET=3600000,DST_OFFSET=0]
In particular I don't understand why for example MONTH is the same for both objects (why isn't the current one 3?) while DAY_OF_YEAR is actually higher in the past Calendar than in the current one.
What am I missing here?
Works as intended. Read the docs.
Android java.util.Calendar looks to behave in a similar way to the standard Java version.
Java docs say:
Any field values set in a Calendar will not be interpreted until it
needs to calculate its time value (milliseconds from the Epoch) or
values of the calendar fields. Calling the get, getTimeInMillis,
getTime, add and roll involves such calculation.
Android docs say:
set(f, value) changes field f to value. In addition, it sets an
internal member variable to indicate that field f has been changed.
Although field f is changed immediately, the calendar's milliseconds
is not recomputed until the next call to get(), getTime(), or
getTimeInMillis() is made. Thus, multiple calls to set() do not
trigger multiple, unnecessary computations.
Related
I have a data class that extends Application and one of the data sets its supposed to be storing is a HashMap of POI locations and Time visited
public class CharacterSheet extends Application {
private HashMap<PointOfInterest, Date> coolDowns = new HashMap<>();
public HashMap GetAllCoolDowns() { return coolDowns; } //dev only?
public Date GetCoolDown(PointOfInterest poi) {return coolDowns.get(poi);}
public Date PutCoolDown(PointOfInterest poi, Date date) {return coolDowns.put(poi, date);}}
Then on a google maps activity I grab the OnPOIclick
#Override
public void onPoiClick(final PointOfInterest poi) {
//POI Cool Down
Date currentTime = Calendar.getInstance().getTime();
Date lastTime = ((CharacterSheet) this.getApplication()).GetCoolDown(poi);//this ONLY returns null??
if (lastTime != null){
int timeDiff = currentTime.compareTo(lastTime);
makeToast("Time Since last visit: " + timeDiff );
} else { makeToast("First");
}
((CharacterSheet) this.getApplication()).PutCoolDown(poi, currentTime);
makeToast("This?" + ((CharacterSheet) this.getApplication()).GetCoolDown(poi));}
The order should be Click poi, Get current time.. get last time visited, if last time is null.. never been before, store time and date in a hashmap with poi as key
Next time turn up and this time last time should not be null as we stored this poi and time already.. but no matter what it returns null..
Last line of code is a makeToast helper telling me what is in the Data Class.. this gives me a date value of when I clicked not a null value
There is a fragment generated later on in the OnPOIClick, but still before the user can do anything, which you end up looking at and have to "back" out of, I don't know how this could effect it as all the code is finished before even calling for data for the fragment but feel It should be mentioned
PlacesClient placesClient = Places.createClient(this);
String placeId = poi.placeId;
List<Place.Field> placeFields = Arrays.asList(Place.Field.ID, Place.Field.TYPES);
FetchPlaceRequest request = FetchPlaceRequest.newInstance(placeId, placeFields);
placesClient.fetchPlace(request).addOnSuccessListener(new OnSuccessListener<FetchPlaceResponse>() {
#Override
public void onSuccess(FetchPlaceResponse fetchPlaceResponse) {
Place place = fetchPlaceResponse.getPlace();
PlaceDataHolder holder = new PlaceDataHolder(place);
String placeName = poi.name;
makeLootFragment(holder,placeName);
The Fragment launched is the entire point of clicking the POI so if this is the case I'll need to think of another way of handling the cooldowns.. but I really don't see why it would interfere.
I was not being thoughtful enough about the PointOfInterest that was returned. It comes with a UUID for every time the request is made, rendering it useless as a key as every time I clicked it changed.. this was discovered by changing my post operation check from making sure it had gone into the hashMap, to seeing the contents of the entire hashMap, soon saw that the entries where building up despite only clicking one poi
To solve this was simple enough. I created a new String variable from poi.name and used that in place of the poi, had to change the HashMap to accept a String rather than a PointOfInterest
What I need specifically is to prevent user from entering date/time that is in the future. That's different than disabling a specific date, since I need to disable ALL dates part a certain date.
Ideally, any future dates should be disabled. For now, I'm just going prevent form submit when user enters invalid time, but disabling unwanted dates would be better.
I went through the javadoc and found nothing. Is it possible? How?
Configuring a range just means disabling the dates outside this range. So the process is the same as the one in the linked answer. You can create a utility method to create filters easier. For example, configureShowRangeHandler admits a Predicate<Date> that will disable the date if the predicate returns false. The enableUntilToday is a simple example to limit selectable dates until today.
{
DatePicker dp = new DatePicker();
Predicate<Date> enableUntilTodayDates = d -> !d.after(new Date());
configureShowRangeHandler(dp, enableUntilTodayDates);
}
static HandlerRegistration configureShowRangeHandler(DatePicker dp, Predicate<Date> fn) {
return dp.addShowRangeHandler(ev -> {
for (Date t = copyDate(ev.getStart()); t.before(ev.getEnd()); addDaysToDate(t, 1)) {
dp.setTransientEnabledOnDates(fn.test(t), t);
}
});
}
copyDate and addDaysToDate are static imported from CalendarUtil
Anyone knows how to disable CURRENT DATE and PREVIOUS DATE'S for WeekDatePicker in Android?
In normal DatePicker we can use this,
calendarView.newState().setMinimumDate(calendar.getTime()).commit();
calendarView.setLimits();
calendarView.addDecorator(new DayViewDecorator() {
#Override
public boolean shouldDecorate(CalendarDay calendarDay)
{
return false;
}
#Override
public void decorate(DayViewFacade view) {
view.setDaysDisabled(true);
}
});
But how to disable CURRENT DATE and PREVIOUS DATE'S in "WeekDatePicker"?
It looks like you're using WeekDatePicker
According to the documentation, calendarView.setLimits() has a From and To as arguments, so you could maybe try nulling the to and setting the from to the current date:
datePicker.setLimits(LocalDate.now(), null);
However, running this it seemed to leave the current day as selected, and when I added a day to this, it would then have the current date indicator as the day before. I've fixed this with the following code, which seems a bit hacky but seems to also work:
datePicker.setDateIndicator(LocalDate.now().plusDays(1), true);
datePicker.setLimits(LocalDate.now().plusDays(1), null);
datePicker.selectDay(LocalDate.now().plusDays(1));
testing this it looks like it has the desired effect:
I have one singleton object which actually store user activity. I wanted to remove this data on certain time ( at every night 12 ). I wanted to know How we can achieve this with out having different thread running.
Add a method to the singleton that returns the last date it ran:
static Date lastRun = new Date(); //when the class initializes
Date lastDateRan() {
return lastRun;
}
Then add another method that checks if today > lastRun (pay attention to check only the date - not time/hour - in case you decide to use TimeStamp or any other library).
Whenever the object is called, check:
if (today > lastRun) {
lastRun = today;
// and clean the object.
}
It won't run every-day exactly at midnight, but it'll have the exact same effect! (the first call after midnight will get "fresh" data)
You can use following code :
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
Object_name.close //your code to cleanup object
}
},
12*60*60*1000 /*time after which it will run again*/
);
As an experiment I ran the following code snippet (simplified):
public class SGamePlay extends Activity implements View.OnClickListener
{
Calendar GlobalCal = null;
public void onCreate(Bundle savedInstanceState)
{
GlobalCal = Calendar.getInstance();
}
long time_in_ms()
{
long ans = -1;
long ans2 = -1;
Calendar LocalCal = Calendar.getInstance();
ans = LocalCal.getTimeInMillis();
ans2 = GlobalCal.getTimeInMillis();
Log.e("game","ans="+ans+" ans2="+ans2);
return ans;
}
// much more code here...
}
The time_in_ms() function is called from a sub thread. The problem is that while ans appears to be a correct, constantly updating value, ans2 appears frozen at its initial value. How could this be?
EDIT: I need to resolve this issue because I want to reduce the need for garbage collection in my program.
Calendar is to be thought of as a "mark" in a calendar. It's more like a point in time, than an interface to the current time. (Why else would it have set-functions?)
So, the reason why ans2 is "frozen" is because GlobalCal.getTimeInMillis(); will always refer to the time when you called Calendar.getInstance() in the constructor (which you did once).
I need to resolve this issue because I want to reduce the need for garbage collection in my program.
Is the garbage collection the bottle neck of your program? Is the number of Calendars the bottle neck of the GC? Have you profiled your program?
Never mind... call System.currentTimeMillis instead.
GlobalCal is initialized in the oncreate method. It is not modified after that. How would you want it to change then ?
By the way, a variable name in java begins with a lowercase letter and follows camel case.