How to write a Quartz timer service that updates every 6 months? - mysql

I want a Quartz timer service for the update code below. Every six months, all users' keys should be updated according to their creationDate:
//dataTypes are date only
List<User> allDbUsers=userRepository.findAll();
Date currDate=new Date();
final long DAY_IN_MILLIS = 1000 * 60 * 60 * 24;
for(User user:allDbUsers)
{
Date creationDate=user.getCreationDate();
String firstKey=user.getFirstKey();
Long diffInDays=(currDate.getTime()-creationDate.getTime())/DAY_IN_MILLIS;
if(diffInDays==180)
{
user.setSecondKey(firstKey);
user.setFirstKey("aH&#KK");
userRepository.saveAndFlush(user);
}
}

You can use Calendar for view diff between dates, for example:
Calendar currentDate = Calendar.getInstance();
Calendar sixMonthAfterCreation;
for (User user : allDbUsers) {
sixMonthAfterCreation = Calendar.getInstance()
sixMonthAfterCreation.setTime(user.getCreationDate());
sixMonthAfterCreation.add(Calendar.MONTH, 6);
String firstKey = user.getFirstKey();
if (currentDate.after(sixMonthAfterCreation)) {
user.setSecondKey(firstKey);
user.setFirstKey("aH&#KK");
userRepository.saveAndFlush(user);
}
}
or if you use java 8 you can convert you creation date to LocalDate and view diff.
If I right understand you, you want use Quartz Scheduler. I did not use it but I think you need implement org.quartz.Job, override execute method and write code for updating users in it.
For more information about Quartz Scheduler look this question
One clarification this code not for run scheduler, it code for method job.excecute(what job must do). Scheduler should run every midnight(for example), then every midnight will be called execute method which find all user for update and do it.

Related

JDBC results set iteration sometimes goes fast and often times goes slow (75x speed difference)

I'm developing a GAS script to retrieve data (~15,000 rows) from an Azure SQL database table into a Sheets spreadsheet. The code works fine but there are huge speed differences from run to run in the results.next() loop
Below is my code (some variable declarations and private stuff removed) and below the code is logs from three executions
function readData() {
Logger.log('Establishing DB connection')
let conn = Jdbc.getConnection(connectionString , user, userPwd);
Logger.log('Executing query')
let stmt = conn.createStatement();
let results = stmt.executeQuery("SELECT * FROM VIEW");
let contents = []
let i = 0
Logger.log("Iterating result set and adding into array")
while (results.next()) {
contents.push([
results.getInt(1),
results.getString(2),
results.getInt(3),
results.getString(4),
results.getInt(5),
results.getString(6),
results.getString(7),
results.getString(8),
results.getFloat(9),
results.getFloat(10),
results.getInt(11),
results.getString(12),
results.getInt(13),
results.getInt(14),
results.getInt(15),
])
//Make log entry every 100th iteration and display the average passed ms per iteration
i++
if(i % 100 == 0){
Logger.log(i)
finish = new Date().getMilliseconds();
Logger.log((finish - start) / i)
}
}
sheet.getRange(2,1,sheet.getLastRow(),15).clearContent()
sheet.getRange(2,1,contents.length,15).setValues(contents)
results.close();
stmt.close();
}
Fast run:
8:41:47 AM Info 11100 Records added
8:41:47 AM Info 8.43ms on average per record
8:41:47 AM Info
8:41:47 AM Info 11200 Records added
8:41:47 AM Info 8.42ms on average per record
8:41:47 AM Info
8:41:48 AM Info 11300 Records added
8:41:48 AM Info 8.42ms on average per record
Slow run:
8:48:01 AM Info 100 Records added
8:48:01 AM Info 162.30ms on average per record
8:48:01 AM Info
8:48:17 AM Info 200 Records added
8:48:17 AM Info 162.84ms on average per record
8:48:17 AM Info
8:48:34 AM Info 300 Records added
8:48:34 AM Info 163.11ms on average per record
Extremely slow run:
8:56:46 AM Info 300 Records added
8:56:46 AM Info 629.08ms on average per record
8:56:46 AM Info
8:57:49 AM Info 400 Records added
8:57:49 AM Info 628.95ms on average per record
8:57:49 AM Info
8:58:52 AM Info 500 Records added
8:58:52 AM Info 629.70ms on average per record
So as seen from above logs, one run of the script can go roughly 75x faster than another. The time per iteration stays the same within a specific run. I'm pretty baffled as to how that's possible. Is there something about the result set object I don't know?
You can submit a bug on Google's Issue Tracker using the following template for Apps Script:
https://issuetracker.google.com/issues/new?component=191640&template=823905
If you have a workspace account, you can also contact Google Workspace support so they can take a look at your issue.

Spoof JSON (or other resource) while loading realtime Web site

I'm trying to write a userscript for a friend. The Website I'm writing it for (app.patientaccess.com) tells you what doctors appointments you have, (among other things). However, in order to write my userscript, I need to know how the app handle appointments for the following year.
At the moment, the only way to know is to wait until the end of the year when my friend starts making appointments for the following year. Since it's an Angular app, I'd rather, if possible, point it to a fabricated JSON file of my creation when the app requests that particular data. In that file I can give it some data for this year and next year and then I can see what happens with appointments made for the following year.
I'm hoping this can be done with an addon for Chrome or Firefox or perhaps some kind of free/open source software.
Thanks in advance.
I came up with a function that will accurately guess there year, given the day name, date and month, if it's within a couple of years either side of the current year.
function calculateYear(dayName, dayOfMonth, monthNum, returnDateObj) {
monthNum -= 1;
maxIterations = 3;
var startYear = (new Date()).getFullYear();
var dateObj = new Date(startYear, monthNum, dayOfMonth);
for (var i = 0; i < maxIterations; i++) {
dateObj.setYear(startYear + (1 * i));
if (dayName == daysOfTheWeek[dateObj.getDay()]) {
return (returnDateObj) ? dateObj : dateObj.getFullYear();
}
dateObj.setYear(startYear - (i + 1));
if (dayName == daysOfTheWeek[dateObj.getDay()]) {
return (returnDateObj) ? dateObj : dateObj.getFullYear();
}
}
return 'No Match';
}
It works a treat, as you can see here.

How to sort objects in DOORS by modification TIME, not just mod DATE?

Sorting objects in DOORS by the built-in DXL Attribute "Last Modified On" only sorts to the date level. That is, after sorting there is no guarantee to the order of Objects that were modified on the same calendar date (but at different times).
That's beyond stupid, especially since other online sources suggest that this field does in fact have this information available - but apparently only sorts on the displayed info, not the underlying data.
Neverminding how I'd LIKE this to work, what can I do instead? Today a module has literally hundreds of changed Objects, but I'm only interested in those altered in the last hour.
Looks like DOORS stores Last Modified On as a date only, without any time. Just to check, I added a layout DXL column with this in it:
Date dMod
dMod = obj."Last Modified On"
dMod = dateAndTime(dMod)
display dMod ""
In return I was greeted with entries like:
09/08/15 00:00:00
I'm not really proud of this next thing, but it sort of does the job. I created a DXL attribute called Last History Date with the following DXL:
History hr
Date dResult = null
Date dHist = null
Date dLastMod = null
dLastMod = obj."Last Modified On"
dLastMod = dateAndTime(dLastMod)
for hr in obj do {
dHist = hr.date
}
if (null dHist) { dResult = dLastMod }
else if (dLastMod > dHist) { dResult = dLastMod }
else { dResult = dHist }
obj.attrDXLName = dResult
If there are no history records, or history is recorded before Last Modified On, it just uses Last Modified On and you'll have to deal with 00:00:00. The history date isn't necessarily the same as Last Modified On -- depends on if you have "Affect change dates" or "Generate history" features turned on for the various object attributes. It's sort of a half-baked solution, but if you really want to sort with time I can't think of another way.

How do I create a SQL calendar with reccuring events that can be easily queried?

I checked several older questions regarding this topic like this one: Calendar Recurring/Repeating Events - Best Storage Method however, the answers are pretty bad performance-wise and cumbersome in implementation. From another answer, it's easy to tell why the accepted answer is a bad idea: a month of events takes 90 queries. Which is unacceptable.
Anyways, here's the issue I'm facing so that you don't have re-read those questions:
Storing events in such a way to allow them to recur. Think Google Calendar where you can specify patterns like "happens on the 1st of the month, every month" or "happens every 2nd monday of the month" (the latter is less important to me.
Querying a list of events for a time period. For example, I want to show someone a list of events for the next 2 months and I don't want to query for every single day of the month. Doing that would just kill the server (per user among thousands of rows of events)
DB agnostic. I use PgSQL and saw many answers for this question on other forums using either MS SQL-specific stuff or Oracle.
I'd appreciate any help! I read a couple of papers on the topic and still can't find something I can make work in SQL specifically.
The solution I have come up with is that I have an event table that has five fields defining the recurrence of the event, as defined below. I then also have a schedule table which I populate with the actual occurrence of the events. I do require an end date, and even when they specify something to go out to a couple years out, it is a monthly type event which does not create that many entries into the schedule table.
So, the event is stored in an event table, with a startDateTime and an endDateTime that describe the entire duration of the event if there is no recurrence. These two datetime fields also define the overall start and end of the event if it is a recurring event. In that same event table, we have the five fields defining recurrence, as laid out below.
The Schedule table stores individual occurrences of each event. So it has an eventId, startDateTime, and endDateTime. This start and end refer only to each occurrence, not the overall span.
For querying for all the scheduled occurrences happening in a period of time, I just query the schedule table checking for any occurrences that match this condition:
select * from schedule where schedule.startDateTime < #queryPeriodEnd and schedule.endDateTime > #queryPeriodStart
This query gives me only the schedule entries that happen partially or wholly within my query period. For getting the event data, it's a simple matter of joining to the event table.
The interesting part is calculating something like the second thursday of the month. That happens in the actual code for figuring out all the scheduled occurrences for a given event. I am also enclosing my code for that below.
EVENT RECURRENCE FIELDS
recurs
0=no recurrence
1=daily
2=weekly
3=monthly
recurs_interval
this is how many of the periods between recurrences. If the event recurs every 5 days, recurs_interval will have a 5 and recurs will have 1. If the event recurs every 3 weeks, recurs_interval will have a 3 and recurs will have a 2.
recurs_day
If the user selected monthly type recurrence, on a given day of the month (ex: 10th or the 14th). This has that date. The value is 0 if the user did not select monthly or specific day of month recurrence. The value is 1 to 31 otherwise.
recurs_ordinal
if the user selected a monthly type recurrence, but an ordinal type of day (ex: first monday, second thursday, last friday). This will have that ordinal number. The value is 0 if the user did not select this type of recurrence.
1=first
2=second
3=third
4=fourth
5=last
recurs_weekdays
for weekly and monthly-ordinal recurrence this stores the weekdays where the recurrence happens. 1=Sunday
2=Monday
4=Tuesday
8=Wednesday
16=Thursday
32=Friday
64=Saturday
So, every 4 weeks on Saturday and Sunday would be
recurs=2, recurs_interval=4, recurs_weekdays=65 (64 + 1)
Similarly, Every three months on the first Friday of the month would be
recurs=3, recurs_interval=3, recurs_ordinal=1, recurs_weekdays=32
CODE
thisEvent.occurrences = new List<ScheduleInstance>();
DateTime currentDateTime = (DateTime) thisEvent.start;
DateTime currentEndTime;
BitArray WeekDayRecurrenceBits = new BitArray(new Byte[] {(Byte) thisEvent.recursWeekdays});
while (currentDateTime < thisEvent.end)
{
currentEndTime = new DateTime(currentDateTime.Year, currentDateTime.Month, currentDateTime.Day,
thisEvent.end.Value.Hour, thisEvent.end.Value.Minute, thisEvent.end.Value.Second);
switch (thisEvent.recurs)
{
case (RecurrenceTypeEnum.None):
AddOccurrenceToRooms(thisEvent, currentDateTime, currentEndTime);
currentDateTime = (DateTime)thisEvent.end;
break;
case (RecurrenceTypeEnum.Daily):
AddOccurrenceToRooms(thisEvent, currentDateTime, currentEndTime);
currentDateTime = currentDateTime.AddDays(thisEvent.recursInterval);
break;
case (RecurrenceTypeEnum.Weekly):
int indexIntoCurrentWeek = (int) currentDateTime.DayOfWeek;
while ((indexIntoCurrentWeek < 7) && (currentDateTime < thisEvent.end))
{
if (WeekDayRecurrenceBits[(int) currentDateTime.DayOfWeek])
{
AddOccurrenceToRooms(thisEvent, currentDateTime, currentEndTime);
}
currentDateTime = currentDateTime.AddDays(1);
currentEndTime = currentEndTime.AddDays(1);
indexIntoCurrentWeek++;
}
currentDateTime = currentDateTime.AddDays(7 * (thisEvent.recursInterval - 1));
break;
case (RecurrenceTypeEnum.Monthly):
if (thisEvent.recursDay == 0)
{
DateTime FirstOfTheMonth = new DateTime(currentDateTime.Year, currentDateTime.Month, 1);
int daysToScheduleOccurrence = ((thisEvent.recursWeekdays - (int)FirstOfTheMonth.DayOfWeek + 7) % 7)
+ ((thisEvent.recursOrdinal - 1) * 7)
- currentDateTime.Day + 1;
if (daysToScheduleOccurrence >= 0)
{
currentDateTime = currentDateTime.AddDays(daysToScheduleOccurrence);
currentEndTime = currentEndTime.AddDays(daysToScheduleOccurrence);
if (currentDateTime < thisEvent.end)
{
AddOccurrenceToRooms(thisEvent, currentDateTime, currentEndTime);
}
}
}
else
{
if (currentDateTime.Day <= thisEvent.recursDay && thisEvent.recursDay <= DateTime.DaysInMonth(currentDateTime.Year, currentDateTime.Month) )
{
currentDateTime = currentDateTime.AddDays(thisEvent.recursDay - currentDateTime.Day);
currentEndTime = currentEndTime.AddDays(thisEvent.recursDay - currentEndTime.Day);
AddOccurrenceToRooms(thisEvent, currentDateTime, currentEndTime);
}
}
currentDateTime = currentDateTime.AddDays((currentDateTime.Day - 1) * -1).AddMonths(thisEvent.recursInterval);
break;
default:
break;
}
}

TimeDelta class in ActionScript?

Is there any ActionScript class which represents "durations of time", similar to the TimeDelta class in Python?
Edit: Thanks for the responses. I should clarify a bit, though: I want be able to ask questions like "how many weeks are between date0 and date1" or "let x represent "one day". What is date2 + x?"
I know I can do all this by representing dates as timestamps... But I'm hoping to find something nicer.
I posted a full AS3 port of the .NET TimeSpan class on this question, which sounds exactly like what you need.
// 5 days from new
var ts : TimeSpan = TimeSpan.fromDays(5);
var now : Date = new Date();
var fiveDaysTime : Date = ts.add(now);
// Diff between dates
var d1 : Date = new Date(2009, 1, 1);
var d2 : Date = new Date(2009, 1, 6);
var ts : TimeSpan = TimeSpan.fromDates(d1, d2);
You can use time() in the Date class to get unix era milliseconds and use that for time delta.
If you subtract two dates:
var dateDiff = date1 - date2;
dateDiff will hold the number of milliseconds between the two dates. You can then convert from milliseconds to whatever useful number you like.
I don't think there is a class which measures change in time in Actionscript 3. According to this blog post on Adventures in Actionscript, timing is very inaccurate in the Flash player on the web. That post is pretty informative and has a class called SuperTimer that might help you. You might want to keep this inaccuracy in mind if using solutions posed by Justin Niessner and toastie.