Add recurring Event in Android Calendar with frequency and recurring date end - java

What I've used as guidelines:
http://developer.android.com/guide/topics/providers/calendar-provider.html#events
http://developer.android.com/reference/android/provider/CalendarContract.Events.html
https://www.rfc-editor.org/rfc/rfc5545#section-3.8.5.3 (for RRULE)
What I have about the Event:
start date
recurring end date
frequency (every day/week/month/year)
What I need, considering:
start date: 11.06.2014 13:00
recurring frequency: "daily"
recurring end date: 14.06.2014 10:00
I need to add an Android event which lasts 1h every day from 11.06 to 14.06 (not inclusive - because start hour is higher than recurring end hour):
11.06 13:00-14:00
12.06 13:00-14:00
13.06 13:00-14:00
What I have until now (ignore non-recurring events - everything works as expected in those cases):
...
ContentValues values = new ContentValues();
values.put(Events.DTSTART, event.getDate().getTime());
if (!event.isRecurring()) { // ignore
values.put(Events.DTEND, event.getEndDate().getTime());
values.putNull(Events.DURATION);
values.putNull(Events.RRULE);
values.putNull(Events.RDATE);
} else {
values.putNull(Events.DTEND);
values.put(Events.DURATION, "PT1H"); // set event duration as 1H - this is ok hardcoded
values.put(Events.RDATE, event.getRecurringEnd().getTime()); // when the event should stop recurring
values.put(Events.RRULE,
Utils.getRRuleForRecurring(event.getRecurring()) + ";UNTIL=" + event.getRecurringEnd().getTime());
}
values.put(Events.TITLE, event.getName());
values.put(Events.DESCRIPTION, event.getDescription() == null ? ""
: event.getDescription());
values.put(Events.CALENDAR_ID, calendarId);
values.put(Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
...
RRule generate method:
public static String getRRuleForRecurring(String recurring) {
recurring = recurring.toLowerCase();
if (recurring.equals("every day")) {
return "FREQ=DAILY";
}
if (recurring.equals("every month")) {
return "FREQ=MONTHLY";
}
if (recurring.equals("every week")) {
return "FREQ=WEEKLY";
}
if (recurring.equals("every year")) {
return "FREQ=YEARLY";
}
return "FREQ=DAILY";
}
What happens: nothing, no errors. But the events doesn't show in the calendar. Again, for the non-recurring ones it works as expected

Related

How do I set a default time to my timepicker?

I have I time picker in my code and when I press the edit text it shows up and everything looks good but I want to set a default time for my time picker so when the user opens the time picker it will be shown a specific time like "3:34 am" as a default time for the user, how can I do that?. Any help will be appreciated. { you can use java and kotlin}
My time picker
private fun showTimePicker() {
picker = MaterialTimePicker.Builder()
.setTimeFormat(TimeFormat.CLOCK_12H)
.setHour(12)
.setMinute(0)
.setTitleText("حدد الموعد الذي تريدة")
.build()
picker.show(supportFragmentManager, "AdhanNotifacations")
picker.addOnPositiveButtonClickListener {
if (picker.hour > 12) {
fajrEditTxt.setHint(String.format("%02d", picker.hour - 12) + ":"
+ String.format("%02d", picker.minute) + " PM")
} else {
fajrEditTxt.setHint(String.format("%02d", picker.hour) + ":"
+ String.format("%02d", picker.minute) + " AM")
}
calender = Calendar.getInstance()
calender[Calendar.HOUR_OF_DAY] = picker.hour
calender[Calendar.MINUTE] = picker.minute
calender[Calendar.SECOND] = 0
calender[Calendar.MILLISECOND] = 0
}
}
You were almost there, just change the value of setHour and setMinute to the hour and minute you want respectively.
I made few changes to your code to show default time of 3:34am:
picker = MaterialTimePicker.Builder()
.setTimeFormat(TimeFormat.CLOCK_12H)
.setHour(3) //3 hour
.setMinute(34) //34 minutes, so 3:34am
.setTitleText("حدد الموعد الذي تريدة")
.build()
If you want to show hour in PM, just add 12 to the hour. For example:
setHour(15)// will show 3pm
Let me know if you have any questions. Thanks.
EDIT
If you want to show time in strict HH:MM format you can keep your code and go as-is. But if you do not wish to be strict, then use the following code:
For example, this will show 9:3PM instead of 09:03PM.
//removed unnecesarry String.format
if(picker.hour > 12){
fajrEditTxt.setHint((picker.hour - 12).toString() + ":" + (picker.minute).toString() + " PM")
}else{
fajrEditTxt.setHint((picker.hour).toString() + ":" + (picker.minute).toString() + " AM")
}
OP asked how to access time:
val time = if(picker.hour > 12){
String.format("%02d",picker.hour - 12) + ":" + String.format("%02d", picker.minute) + " PM"
}else{
String.format("%02d",picker.hour) + ":" + String.format("%02d", picker.minute) + " AM"
}
time //use time, its in HH:MM format
fajrEditTxt.setHint(time)
I'm not understanding what it is you're asking, but if you're trying to sort the times in the library, you could place the times in a list and then sort the list, or if you just want to compare the magnitude values of two different times with just a couple of lines of code, you could remove the time separators from the time strings, convert those values to numbers ( of your choice ) and compare. The numbers generated from the conversions have no real world values, but their magnitudes with respect to one another will always be valid.
Oh. Snippet editor does not support touch devices.
Ok then.
String time = "00:00";
time.replace( ":", "" );
Double d = Double.parseDouble( time );
So now you can do with d as you wish. As you can see you don't have to bother with whether any of the values are to great. If you're dealing with a pair of valid times it's their relative magnitudes that matters. Of course if the time is in 12 Hr format, you'll need to strip the time modifier ( A, a, P, p, Am, AM .... ) too.

Quartz CronTrigger - fire time

I`m using quartz cron expression to build n schedule events, i have a start date and end date, but, when a crate a expression, the second event (getNextValidTimeAfter) its wrong...
08-03-19 08:00:00 -- first date
05-04-19 08:00:00 -- wrong date...
05-07-19 08:00:00
04-10-19 08:00:00
Follow the expression
0 0 8 ? 1/3 FRI#1 *
org.quartz.CronExpression expression = new org.quartz.CronExpression(cronExpression.getExpression());
List<Schedule> scheduleList = new ArrayList<>();
Date nextExecutionDate = cronExpression.getStartDate();
boolean first = true;
while (true) {
Schedule schedule = new Schedule();
schedule.setStatus(Enums.StatusSchedule.PROGRAMADO);
schedule.setCronExpression(cronExpression);
schedule.setServiceOrderType(cronExpression.getServiceOrderType());
schedule.setEstimatedTime(cronExpression.getEstimatedTime());
if (first == false)
nextExecutionDate = expression.getNextValidTimeAfter(nextExecutionDate);
else
first = false;
if (cronExpression.getEndDate().compareTo(nextExecutionDate) <= 0)
break;
schedule.setScheduleDate(nextExecutionDate);
if (CollectionUtils.isEmpty(schedule.getScheduleItems()))
schedule.setScheduleItems(new ArrayList<>());
for (GenericShelfData genericShelfData : genericShelfDataList) {
ScheduleItem scheduleItem = new ScheduleItem();
scheduleItem.setStatus(Enums.StatusSchedule.PROGRAMADO);
scheduleItem.setSchedule(schedule);
scheduleItem.setGenericShelfData(genericShelfData);
scheduleItem.setScheduleSeparate(Enums.YesOrNo.NAO);
schedule.getScheduleItems().add(scheduleItem);
}
scheduleList.add(schedule);
}
My expression was wrong... The correct is.. 0 0 8 ? 3/3 FRI#2 *
I use this site for build a expression: https://www.freeformatter.com/cron-expression-generator-quartz.html

Check if timestamp coming from DB is 2hrs ago or older

I want to compare a timestamp coming from db and see if it's 1 hr 59 minutes old or not,I have implemented the following code.Please review it and suggest changes:
private static final long TIME_LIMIT= 7199 * 1000;
private Token getTokenFromDB ()
{
InterfaceRequestResponseDAO.getInstance ().getEntityManager ().createNamedQuery (InterfaceRequestResponse.Queries.GET_TOKEN) //
.setParameter ("token", InterfaceRequestResponse.COL_RESPONSEEND)//
.setParameter ("interfaceRequestResponseID", this.getInterfaceRequestResponseID ())//
.executeUpdate ();
// authenticationToken.getResponseEnd ();
long responseEnd = System.currentTimeMillis ();
if (responseEnd < TIME_LIMIT)
return authenticationToken;
else
return NOT_VALID;
I suggest you to use JodaDate..
I implemented the same thing in a project. What I did was I saved the expire time instead of the timestamp created. This makes it more easy to handle.
Everytime I refresh the token, I update the expireTime by adding the offset
DateTime expireTime = new DateTime(new Date());
expireTime = expireTime.addHours(2);//because token expires in 2 hours
And then I store this time.
When I'm requesting, I used to check if the current time < expire time.
DateTime expireTime = getTimeFromDB();
DateTime now = new DateTime(new Date());
if( now.isBefore(expireTime))
{
//valid token.
}
else
{
// refresh your token and update the time.
}

MS Project showing incorrect start date and enddate

I'm using mpxj 4.5 to export ms project. When i open mpx file by ms project, I'm getting incorrect start date and finish date, but it's calculating duration correctly. What am i doing wrong, please tell.
To create mpx task I use following parametrs of mpxj:
public ProjectFile exportToMSProject(Integer projectID){
file.setAutoTaskID(true);
...........
}
private void createMSProjectTask(ProjectFile file, EUser user, ETask eTask)
Task task = file.addTask();
task.setUniqueID(eTask.getObjectID());
task.setName(eTask.getName());
task.setNotes(eTask.getDescription());
task.setType(TaskType.FIXED_DURATION);
long workTime = 0;
if(eTask.getDueDate() != null && eTask.getStartDate() != null){
workTime = (eTask.getDueDate().getTime() - eTask.getStartDate().getTime()) / (1000 * 60 * 60);
}
if(eTask.isAllDay()){
task.setDuration(Duration.getInstance(workTime / 24, TimeUnit.DAYS));
}else {
task.setDuration(Duration.getInstance(workTime, TimeUnit.HOURS));
}
if(eTask.getStartDate() != null)
task.setStart(user.getUserDate(eTask.getStartDate())); //get time from user time zone
if(eTask.getDueDate() != null)
task.setFinish(user.getUserDate(eTask.getDueDate()));
task.setPercentageComplete(eTask.getPercent() != null ? eTask.getPercent() : new Float(0.0));
if(eTask.getActualStartDate() != null)
task.setActualStart(eTask.getActualStartDate());
}
I'm getting repeatedly startdate and incorrect enddate. What is the problem here? Any suggestion will be appreciated.
I had the same issue. From my point of view, if you not have any predecessor or actual start date of your tasks, mpxj sets startdate automatically, I mean, it gets startdate from your project header or first task's start date of your project. That's why you got repeated startdate.
Here is the simple example (I'm using mpxj 4,5 and creating .mpx file):
SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
ProjectFile file = new ProjectFile();
ProjectHeader header = file.getProjectHeader();
header.setStartDate(df.parse("01/05/2014"));
Task task1 = file.addTask();
task1.setName("Summary Task");
Task task2 = task1.addTask();
task2.setName("First Sub Task");
task2.setDuration(Duration.getInstance(10.5, TimeUnit.HOURS));
task2.setStart(df.parse("01/05/2014"));
task2.setPercentageComplete(NumberUtility.getDouble(50.0));
Task task3 = task1.addTask();
task3.setName("Second Sub Task");
task3.setStart(df.parse("11/05/2014"));
task3.setDuration(Duration.getInstance(10, TimeUnit.HOURS));
Task milestone1 = task1.addTask();
milestone1.setName("Milestone");
milestone1.setStart(df.parse("21/05/2014"));
milestone1.setDuration(Duration.getInstance(0, TimeUnit.HOURS));
Task task4 = file.addTask();
task4.setName("Last Task");
task4.setDuration(Duration.getInstance(8, TimeUnit.HOURS));
task4.setStart(df.parse("02/05/2014"));
task4.setPercentageComplete(NumberUtility.getDouble(70.0));
ProjectWriter writer = getWriter(filename);
writer.write(file, filename);
As you have seen, I'm not giving any predecessor or actual start date. If you run this you will get following result.
In order to get start date correctly, i gave an actual startdate not a startdate, and it worked. In addition if you have predecessor, you will get parent task's due date as a startdate.
task.setActualStart(df.parse("02/05/2014"));
By the way, ms project sets due date based on your duration.

Halting program execution between certain hours of the week

I am writing a Java program that is required to copy files and folders between the following hours:
Mon - 18:00 to 06:30
Tue - 18:00 to 06:30
Wed - 18:00 to 06:30
Thu - 18:00 to 06:30
Fri - 18:00 to 06:30
Sat - all day
Sun - all day
The program will run continuously until it has finished copying all files and folders. However, outside of the above hours the program should just sleep.
I am using a properties file to store the above settings.
UPDATE
I am looking for the simplest possible implementation including the format of the properties in the properties file as well as the code that will make the checks.
I would do it like this
final Map<Integer, String> schedule = new HashMap<>();
// parse your settings and fill schedule
schedule.put(Calendar.MONDAY, "18:00 to 06:30");
// ...
// create timer to fire e.g. every hour
new Timer().scheduleAtFixedRate(new TimerTask() {
public void run() {
Calendar c = Calendar.getInstance();
String s = schedule.get(c.get(Calendar.DAY_OF_WEEK));
if (withinTimeRange(c, s)) { // implement withinTimeRange func
// copy files
}
}}, 0, 1000 * 3600);
Since your program is going to run continuously, the simplest solution is to check the day and time before copying a file. If the time is during off hours, go ahead and copy the next file, otherwise Thread.sleep.
If this is an internal, one-off kind of program, I would go ahead and hard-code the business hours instead of reading the properties file. No need to add complexity.
whenever your program is launched, get the current time, and check day today's day.
check whether it lies in permissible time if yes let it continue. If not, find the time at 00:00am of that 'day'. and find the time at xx:yyZZ (start of permissible time). calculate the difference, and let the program sleep for that much of time.
Thank you for your suggestions.
I came up with a working solution in the end which if it gets enough points I will mark as the answer. The way I attempted to solve this problem was by thinking about non-working hours rather than working hours. This code is just for illustration
# Properties
Mon = 06:30-18:00
Tue = 06:30-18:00
Wed = 06:30-18:00
Thu = 06:30-18:00
Fri = 06:30-18:00
Loop over the properties to get their values
String[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
Map<Integer, Integer[]> nonWorkingHours = new HashMap<Integer, Integer[]>();
for( int i = 0; i < days.length; i++ ) // for each property in file
{
// excluded implementation of getConfig
String prop = getConfig( days[ i ] ); // e.g. "06:00-19:00"
// +1 to match CALENDAR.DAY_OF_WEEK
nonWorkingHours.put( i + 1, getHours( prop );
}
My function to parse property excluding error handling
// e.g. if prop = "06:00-19:00" then { 6, 0, 19, 0 } is returned
public Integer[] getHours( String prop )
{
String times = prop.split( "(:|-)" );
Integer[] t = new Integer[4];
for( int i = 0; i < times.length; i++ )
{
t[i] = Integer.parseInt( times[i] );
}
return t;
}
And finally the function that implements the halt
private void sleepIfOutsideWorkingHours()
{
Integer[] data = nonWorkingHours.get( currentDay );
if( data != null )
{
Calendar c = Calendar.getInstance();
Integer currentSeconds = ( Calendar.HOUR_OF_DAY * 3600 ) + ( Calendar.MINUTE * 60 );
Integer stopFrom = ( data[ 0 ] * 3600 ) + ( data[ 1 ] * 60 );
Integer stopTill = ( data[ 2 ] * 3600 ) + ( data[ 3 ] * 60 );
if( currentSeconds > stopFrom && currentSeconds < stopTill )
{
Integer secondsDiff = stopTill - currentSeconds;
if( secondsDiff > 0 )
{
try
{
Thread.sleep( secondsDiff * 1000 ); // turn seconds to milliseconds
}
catch( InterruptedException e )
{
// error handling
}
}
}
}
}
And finally just call the function below just before copying each file and if it is being run outside working hours it will stop the program.
sleepIfOutsideWorkingHours();
I am sure there is a simpler way of doing it :-) but there it is.
You should try using a Continuous Integration system. That scenario can be easily set up using Jenkins CI for example.
The reason i advise doing it so in a ambient like that is that you can keep a better control on the history of your program runs.

Categories