Hi I am tring to Create an app which add events to calendar. For example I need to create an event on every Saturday until dec 31ist.
The following are the attributes that I set for creating events,
event.put(CalendarContract.Events.CALENDAR_ID, 1);
event.put(CalendarContract.Events.TITLE, title);
event.put(CalendarContract.Events.DESCRIPTION, description);
event.put(CalendarContract.Events.EVENT_LOCATION, location);
event.put(CalendarContract.Events.DTSTART, sDate);
event.put(CalendarContract.Events.DURATION,"P50S");
event.put(CalendarContract.Events.ALL_DAY, 0);
event.put(CalendarContract.Events.HAS_ALARM, hasAlarm);
event.put(CalendarContract.Events.EVENT_TIMEZONE, timeZone);
event.put(CalendarContract.Events.RRULE, "FREQ=WEEKLY;BYDAY=SA;UNTIL=20151230");
mContext.getContentResolver().insert(baseUri, event);
But it create an event for the given date (sDate) and then create every Saturday. But how can I avoid that one event which created on given date (sDate)
I had the same problem. You need to check your reccurrence rule for day of week and offset your DTSTART to the nearest Saturday (or any other weekday that your recurrence rule contains). To give you rough example how to do that I'm attaching code from Android Calendar app that offsets start time and end time of the event based on reccurence rule string, and returns two long values - new start time and new end time if offset was applied, or null if it wasn't. EventRecurrence class can be found via search on GrepCode, its part of Android calendar app
public static long[] offsetStartTimeIfNecessary(long startMilis, long endMilis, String rrule) {
if (rrule == null || rrule.isEmpty() || rrule.replace("RRULE:", "").isEmpty()) {
// No need to waste any time with the parsing if the rule is empty.
return null;
}
long result[] = new long[2];
Calendar startTime = Calendar.getInstance();
startTime.setTimeInMillis(startMilis);
Calendar endTime = Calendar.getInstance();
endTime.setTimeInMillis(endMilis);
EventRecurrence mEventRecurrence = new EventRecurrence();
mEventRecurrence.parse(rrule.replace("RRULE:", ""));
// Check if we meet the specific special case. It has to:
// * be weekly
// * not recur on the same day of the week that the startTime falls on
// In this case, we'll need to push the start time to fall on the first day of the week
// that is part of the recurrence.
if (mEventRecurrence.freq != EventRecurrence.WEEKLY) {
// Not weekly so nothing to worry about.
return null;
}
if (mEventRecurrence.byday == null ||
mEventRecurrence.byday.length > mEventRecurrence.bydayCount) {
// This shouldn't happen, but just in case something is weird about the recurrence.
return null;
}
// Start to figure out what the nearest weekday is.
int closestWeekday = Integer.MAX_VALUE;
int weekstart = EventRecurrence.day2TimeDay(mEventRecurrence.wkst);
int startDay = startTime.get(Calendar.DAY_OF_WEEK) - 1;
for (int i = 0; i < mEventRecurrence.bydayCount; i++) {
int day = EventRecurrence.day2TimeDay(mEventRecurrence.byday[i]);
if (day == startDay) {
// Our start day is one of the recurring days, so we're good.
return null;
}
if (day < weekstart) {
// Let's not make any assumptions about what weekstart can be.
day += 7;
}
// We either want the earliest day that is later in the week than startDay ...
if (day > startDay && (day < closestWeekday || closestWeekday < startDay)) {
closestWeekday = day;
}
// ... or if there are no days later than startDay, we want the earliest day that is
// earlier in the week than startDay.
if (closestWeekday == Integer.MAX_VALUE || closestWeekday < startDay) {
// We haven't found a day that's later in the week than startDay yet.
if (day < closestWeekday) {
closestWeekday = day;
}
}
}
if (closestWeekday < startDay) {
closestWeekday += 7;
}
int daysOffset = closestWeekday - startDay;
startTime.add(Calendar.DAY_OF_MONTH, daysOffset);
endTime.add(Calendar.DAY_OF_MONTH, daysOffset);
result[0] = startTime.getTimeInMillis();
result[1] = endTime.getTimeInMillis();
return result;
}
Related
My week start from Friday and end from Thursday, and i get a list of weeks of current month weeks.
In my Code every thing working fine but get current month four weeks but i want previous four weeks not next weeks of current week.
public void getWeeksOfMonth( int year) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
Calendar cal = Calendar.getInstance();
int currentmonth = cal.get(Calendar.MONTH);
int val = 0;
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, currentmonth);
cal.set(DAY_OF_MONTH, 1);
int ndays = cal.getActualMaximum(DAY_OF_MONTH);
System.out.println(ndays + "<<<ff");
while (cal.get(DAY_OF_WEEK) != FRIDAY) {
cal.add(DAY_OF_MONTH, 1);
ndays--;
}
int remainingDays = ndays % 7;
if (remainingDays == 0)
ndays += 7;
else
ndays = ndays + 7 - remainingDays;
int inc = 1;
for (int i = 1; i <= ndays; i++) {
String day = sdf.format(cal.getTime());
System.out.println(day + "<<<");
Log.e("quest", day + "<<<");
inc++;
if (val == 0) {
firstweek = day.substring(0, 6);
// weeklist.add(firstweek);
val = 1;
}
if (i % 7 == 0) {
String s = day.substring(0, 6);
weeklist.add(firstweek + " to " + s);
val = 0;
Log.e("weekdayss", "=======week days===========" + weeklist);
inc = 0;
}
if (inc >= 1 && i == ndays) {
for (int ii = inc; ii <= 6; ii++) {
String dayi = sdf.format(cal.getTime());
System.out.println(dayi + "<<<");
Log.e("quest1", dayi + "<<<");
inc++;
}
}
cal.add(Calendar.DATE, 1);
}
if (weeklist.size() == 5) {
weeklist.remove(4);
}
if (weeklist.size() == 6) {
weeklist.remove(5);
weeklist.remove(4);
}
}
Problem
Want to get previous four weeks, not current Month four weeks
OUTPUT
[
02-Mar to 08-Mar
09-Mar to 15-Mar
16-Mar to 22-Mar
23-Mar to 29-Mar
]
A good alternative is to use the threeten backport - in Android here's how to configure it. Or, if you're using API level >= 26, just use the java.time classes.
This API makes things much easier. You can use the WeekFields class to define your week (starting on Friday):
// week starts on Friday
WeekFields wf = WeekFields.of(DayOfWeek.FRIDAY, 1);
The first parameter (DayOfWeek.FRIDAY) is the first day of the week, and the second parameter is the number of days in the first week. Check the documentation for more details about how these fields affect the class behaviour.
To get the current date, you can use the LocalDate class:
// current date
LocalDate dt = LocalDate.now();
Then you make a loop that subtracts a certain number of weeks, and use the WeekFields to get the first and last day of each week. I also used a DateTimeFormatter to print the dates to same format of your output:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd-MMM", Locale.ENGLISH);
// get previous 4 weeks
for (int i = 4; i >= 1; i--) {
LocalDate pastWeek = dt.minusWeeks(i);
LocalDate startOfWeek = pastWeek.with(wf.dayOfWeek(), 1);
LocalDate endOfWeek = pastWeek.with(wf.dayOfWeek(), 7);
// you can add this String to your weekList
String week = startOfWeek.format(fmt) + " to " + endOfWeek.format(fmt);
System.out.println(week);
}
Output:
23-Feb to 01-Mar
02-Mar to 08-Mar
09-Mar to 15-Mar
16-Mar to 22-Mar
How to Change start date and end date of month in calroid calendar lib if i want to modify calendar with shift my month start from 15 jan 2016 to 16 feb 2016.
Hello using following modification in CalendarHelper class you can set start date of month for shift calendar. I am using following library for calendar view https://github.com/roomorama/Caldroid
please modify getFullWeeks method
/**
* Retrieve all the dates for a given calendar month Include previous month,
* current month and next month.
*
* #param month
* #param year
* #param startDayOfWeek : calendar can start from customized date instead of Sunday
* #return
*/
public static ArrayList<DateTime> getFullWeeks(int month, int year, int startDayOfWeek,int startDayOfMonth, boolean sixWeeksInCalendar) {
ArrayList<DateTime> datetimeList = new ArrayList<DateTime>();
int dayCount=startDayOfMonth;
DateTime firstDateOfMonth = new DateTime(year, month, 1, 0, 0, 0, 0);
DateTime firstDateOfMonthToSet = new DateTime(year, month, dayCount, 0, 0, 0, 0);
int daysToAdd=firstDateOfMonth.getNumDaysInMonth()-dayCount;
DateTime lastDateOfMonth = firstDateOfMonthToSet.plusDays(daysToAdd);
DateTime lastDateOfMonthTpSet =firstDateOfMonthToSet.plusDays(firstDateOfMonth.getNumDaysInMonth()-1);
// Add dates of first week from previous month
// int weekdayOfFirstDate = firstDateOfMonth.getWeekDay();
//dr
int weekdayOfFirstDate = firstDateOfMonthToSet.getWeekDay();
// If weekdayOfFirstDate smaller than startDayOfWeek
// For e.g: weekdayFirstDate is Monday, startDayOfWeek is Tuesday
// increase the weekday of FirstDate because it's in the future
if (weekdayOfFirstDate < startDayOfWeek) {
weekdayOfFirstDate += 7;
}
while (weekdayOfFirstDate > 0) {
DateTime dateTime = firstDateOfMonthToSet.minusDays(weekdayOfFirstDate
- startDayOfWeek);
if (!dateTime.lt(firstDateOfMonthToSet)) {
break;
}
datetimeList.add(dateTime);
weekdayOfFirstDate--;
}
// Add dates of current month
for (int i = 0; i < lastDateOfMonth.getDay(); i++) {
datetimeList.add(firstDateOfMonthToSet.plusDays(i));
}
// Add dates of last week from next month
int endDayOfWeek = startDayOfWeek - 1;//dr
// int endDayOfWeek = startDayOfWeek;
if (endDayOfWeek == 0) {
endDayOfWeek = 7;
}
if (lastDateOfMonthTpSet.getWeekDay() != endDayOfWeek) {
int i = 1;
while (true) {
DateTime nextDay = lastDateOfMonthTpSet.plusDays(i);
datetimeList.add(nextDay);
i++;
if (nextDay.getWeekDay() == endDayOfWeek) {
break;
}
}
}
// Add more weeks to fill remaining rows
if (sixWeeksInCalendar) {
int size = datetimeList.size();
int row = size / 7;
int numOfDays = (6 - row) * 7;
DateTime lastDateTime = datetimeList.get(size - 1);
for (int i = 1; i <= numOfDays; i++) {
DateTime nextDateTime = lastDateTime.plusDays(i);
datetimeList.add(nextDateTime);
}
}
return datetimeList;
}
Hope this will help you :)
I'm using UsageStatsManager API to get usage statistics for a certain time interval. All works fine if I use the predefined intervals i.e. INTERVAL_DAILY, INTERVAL_WEEKLY, INTERVAL_MONTHLY, INTERVAL_YEARLY. But if I want to view the data for the past 2 or 3 hours, I am getting today's data for the whole day. I have tried using Calendars and System.currentTimeMillis() but that didn't give me filtered results.
Calendar approach :
Calendar startCalendar = Calendar.getInstance();
startCalendar.add(Calendar.HOUR_OF_DAY, -2);
Calendar endCalendar = Calendar.getInstance();
And pass this to queryUsageStats method like this:
usageList = usm.queryUsageStats(interval, startCalendar.getTimeInMillis(), endCalendar.getTimeInMillis());
where interval is INTERVAL_BEST.
System.currentTimeMillis() approach :
long startTime = System.currentTimeMillis() - 7200*1000 // 7200 seconds i.e. 2 hrs
long endTime = System.currentTimeMillis();
Pass this to queryUsageStats just like above :
usageList = usm.queryUsageStats(interval, startTime, endTime);
where interval is again INTERVAL_BEST.
I'd like to know whether it's possible to get data for this duration i.e. less than a day, as the INTERVAL_BEST hasn't been documented properly to include this information. Any help would be appreciated as I'm stuck on this problem.
As UsageStatsManager doc says:
A request for data in the middle of a time interval will include that interval.
It seems that usage data is stored in buckets, and minimum bucket is a day, so you can't query usage stats for period less than a day. Even if you query a one-hour interval for a particular day, usage stats for the whole day is returned.
A little late to the party, but I think this might be useful to some.
You could use the queryEvents(long startTime, long endTime) from UsageStatsManager for achieving the desired result. The method could look like this (inspired by this post):
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public HashMap<String, AppUsageInfo> queryUsageStatistics(Context context, long startTime, long endTime) {
UsageEvents.Event currentEvent;
List<UsageEvents.Event> allEvents = new ArrayList<>();
HashMap<String, AppUsageInfo> map = new HashMap<>();
UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
assert mUsageStatsManager != null;
// Here we query the events from startTime till endTime.
UsageEvents usageEvents = mUsageStatsManager.queryEvents(startTime, endTime);
// go over all events.
while (usageEvents.hasNextEvent()) {
currentEvent = new UsageEvents.Event();
usageEvents.getNextEvent(currentEvent);
String packageName = currentEvent.getPackageName();
if (currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED || currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED ||
currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_STOPPED) {
allEvents.add(currentEvent); // an extra event is found, add to all events list.
// taking it into a collection to access by package name
if (!map.containsKey(packageName)) {
map.put(packageName, new AppUsageInfo());
}
}
}
// iterate through all events.
for (int i = 0; i < allEvents.size() - 1; i++) {
UsageEvents.Event event0 = allEvents.get(i);
UsageEvents.Event event1 = allEvents.get(i + 1);
//for launchCount of apps in time range
if (!event0.getPackageName().equals(event1.getPackageName()) && event1.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED) {
// if true, E1 (launch event of an app) app launched
Objects.requireNonNull(map.get(event1.getPackageName())).launchCount++;
}
//for UsageTime of apps in time range
if (event0.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED &&
(event1.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED || event1.getEventType() == UsageEvents.Event.ACTIVITY_STOPPED)
&& event0.getPackageName().equals(event1.getPackageName())) {
long diff = event1.getTimeStamp() - event0.getTimeStamp();
Objects.requireNonNull(map.get(event0.getPackageName())).timeInForeground += diff;
}
}
// and return the map.
return map;
}
The AppUsageInfo class would be:
public class AppUsageInfo {
public long timeInForeground;
public int launchCount;
AppUsageInfo() {
this.timeInForeground = 0;
this.launchCount = 0;
}
}
To then get the usage stats for the last two hours, simply call
Calendar startCalendar = Calendar.getInstance();
startCalendar.add(Calendar.HOUR_OF_DAY, -2);
Calendar endCalendar = Calendar.getInstance();
HashMap<String, AppUsageInfo> result = queryUsageStatistics(context, startCalendar.getTimeInMillis(), endCalendar.getTimeInMillis();
in my app I'm updating some stuff if the time is between certain hours of the day which the user choose. It works fine if the user chooses something like "07-21", but not with "21-07" which is over the night.
How I'm doing to check the time is I'm getting the current hour and converting it into milliseconds. Then I check if the current milli is between the chosen hours (those are also converted into milliseconds).
Like this:
if (currentMilli >= startHourMilli && currentMilli <= endHourMilli)
The problem: It doesn't work if the user chooses anything that is over midnight (19-08 for example).
I've tried a lot of stuff but I just can't figure out how to do this.
Any help is appreciated!
Do you increase the day of the year by 1 when you're passing midnight? Otherwise your
startHourMilli might be greater than endHourMilli and your if-clause will always be false.
The solution is to use the add-method of the Calendar class. Therefore I calculate the interval's length in hours and add this value to our Calendar instance.
int start = 21; // let's take your failing example: 21-07
int end = 7;
int hours = (end - start) % 24; // here hours will be 14
Calendar cal = Calendar.getInstance();
// set calendar to TODAY 21:00:00.000
cal.set(Calendar.HOUR_OF_DAY, start);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long startHourMilli = cal.getTimeInMillis();
// add 14 hours = TOMORROW 07:00:00.000
cal.add(Calendar.HOUR_OF_DAY, hours);
long endHourMilli = cal.getTimeInMillis();
Let me know if this helps :)
Simplest way to check..
val isDayTime : Boolean
get() {
val cal = Calendar.getInstance()
val hour = cal.get(Calendar.HOUR_OF_DAY)
return hour in 8..20
}
Date has the functions before and after for comparing two dates.
Hope this documentation helps you:
http://developer.android.com/reference/java/util/Date.html#after(java.util.Date)
http://developer.android.com/reference/java/util/Date.html#before(java.util.Date)
Best regards.
I'm answering my own question because I think I came up with something that might work for what I'm trying to do:
if(endHourMilli < startHourMilli){
if(currentMilli >= startHourMilli && currentMilli <= 23*3600000 || currentMilli >= 0 && currentMilli <= endHourMilli){
//Do whatever
}
}else{
if (currentMilli >= startHourMilli && currentMilli <= endHourMilli) {
//Do whatever
}
}
It should work even if endMilli is less than startMilli, or have I screwed something up here?
I know I'm a little late to the party, but recently I developed android app that needed to work within given timeframe, and since I didn't like working with Calendar I ended up using something like this:
// if start hour is later than end hour
// example: start = 21, end = 07
int startHourMilli = 21, endHourMilli = 07;
// just add one day (in your case in millis)
if (startHourMilli > endHourMilli) endHourMilli += 24 * 60 * 60 * 1000;
// now here you can check without any problems
if(currentMilli >= startHourMilli && currentMilli < endHourMilli){
// within timeframe, do stuff you need
} else {
// not in timeframe, find solution
}
Now I know that you found yourself a solution, but I think that my approach may be a little more understandable (at least to newbies that might get confused).
You can always use simple if / else for 24 hour format, without using functions or additional calculations:
For Example1: Full time period from StartHour to StopHour(stop hour include all minutes)
int StartHour = 23; //start from 23:00
int StopHour = 9; // until current hour is 9 that will include until 9:59
int CurrentHour = 2;
if (StartHour > StopHour)
{
if (CurrentHour < StartHour && StopHour < CurrentHour)
{Inside = false;}
else
{Inside = true;}
}
else
{
if (CurrentHour >= StartHour && StopHour >= CurrentHour)
{Inside = true;}
else
{Inside = false;}
}
At the end if Inside == true CurrentHour is in time range StartHour - StopHour(full stop hour)
And do something else if both equal:
if (StartHour == StopHour) {..............};
For Example2: If you want to stop at this exact StopHour hour, you need some changes:
int StartHour = 23; //start from 23:00
int StopHour = 9; // this will stop after 8:59
int CurrentHour = 2;
if (StartHour2 > StopHour2)
{
if (Hr24 < StartHour2 && StopHour2 <= Hr24)
{Quiet = false;}
else
{Quiet = true;}
}
else
{
if (Hr24 >= StartHour2 && StopHour2 > Hr24)
{Quiet = true;}
else
{Quiet = false;}
}
At the end if Inside == true CurrentHour is in time range StartHour - StopHour(exact)
I think that ottel142 is almost ok but it shoud be:
public static boolean checkIfNight() {
int start = 21;
int end = 7;
int hours = 24 - start + end;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, start);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long startHourMilli = cal.getTimeInMillis();
KLog.e(cal.getTime());
cal.add(Calendar.HOUR_OF_DAY, hours);
long endHourMilli = cal.getTimeInMillis();
long currentMilli = Calendar.getInstance().getTimeInMillis();
if (currentMilli >= startHourMilli && currentMilli <= endHourMilli)
return true;
else return false;
}
The number of "week of year" returned from a Date is wrong.
This is my code:
Calendar c = Calendar.getInstance();
c.setTime(my_date);
int num_week = c.get(Calendar.WEEK_OF_YEAR);
If my_date (type Date) is 01/01/2011, I supposed that "week of year" is 1. But it returned 52.
I try to test with these methods but I don't obtain anything:
c.setFirstDayOfWeek(6);
c.setMinimalDaysInFirstWeek(1)
If It's interesting, I'm from Spain, and our week begin on Monday.
Have I to do anything for obtain right results?
Thanks!
This may be Android/Harmony-specific. For example, this works for me with desktop Java:
import java.util.*;
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(2011, 0, 1, 0, 0, 0);
System.out.println(calendar.get(Calendar.WEEK_OF_YEAR)); // Prints 52
calendar.setMinimalDaysInFirstWeek(1);
System.out.println(calendar.get(Calendar.WEEK_OF_YEAR)); // Prints 1
}
}
Can you confirm that the exact same code (modulo logging options) logs 52 twice on Android?
Here you can view the reference by oracle
https://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html
And I have placed a quick solution to find the week count of current day. You can alter and optimize as your way. Also set according to your convenient GMT value
public static int getWeeksOfMonth() {
DATESTATUS = false;
VALUESTATUS = false;
int weekCount;
WEEK_OF_MONTH= -1;
// get the supported ids for GMT+04:00 (Pacific Standard Time)
String[] ids = getAvailableIDs(4 * 60 * 60 * 1000);
// if no ids were returned, something is wrong. get out.
if (ids.length == 0)
return WEEK_OF_MONTH;
// create a Pacific Standard Time time zone
SimpleTimeZone pdt = new SimpleTimeZone(4 * 60 * 60 * 1000, ids[0]);
// create a GregorianCalendar with the Pacific Daylight time zone
// and the current date and time
Calendar calendar = new GregorianCalendar(pdt);
Date trialTime = new Date();
calendar.setTime(trialTime);
weekCount = calendar.get(Calendar.WEEK_OF_YEAR);
return recursiveWeekCountCheck(calendar, weekCount);
}
private static int recursiveWeekCountCheck(Calendar calendar, int weekCount) {
if (calendar.get(Calendar.MONTH) == Calendar.DECEMBER && weekCount == 1) {
DATESTATUS = true;
calendar.add(Calendar.DAY_OF_MONTH, -1);
weekCount = calendar.get(Calendar.WEEK_OF_YEAR);
recursiveWeekCountCheck(calendar, weekCount);
}
if (!VALUESTATUS){
VALUESTATUS = true;
if (DATESTATUS) {
weekCount++;
WEEK_OF_MONTH = weekCount;
} else {
WEEK_OF_MONTH = weekCount;
}
}
return WEEK_OF_MONTH;
}
At the end just call the method getWeeksOfMonth();