How to validate if current date time is within Spring Cron Expression? - spring

I have a Spring Cron Expression like */10 * 9-17 * * MON-FRI
I want to find out if the current time or any given time is within the range or not.
I know I can use CronExpression class and use the next() method. But it gives me the next valid runnable time.
Thanks

A cron expression does not define a range or ranges of time. Rather, it defines distinct points in time throughout a year. In many cases, like with your example, cron expressions are viewed as describing distinct points in time throughout each week.
Since cron doesn't define a range, it doesn't make sense to ask if a particular time is "within the range or not". This is why it has only a next() method...pretty much all you can do is ask what the next point in time is given a time to start from.
If this doesn't clear up your problem for you, I would suggest that you edit your question and describe your use case. What is it that you are actually trying to accomplish?

It is possible to check if a time matches a specific cron, if you truncate a given timestamp to seconds and do a little tweaking with CronExpression#next(). Basically it'll ask "is the current timestamp a valid time for cron execution", even if it isn't really a range.
Within CronExpression#next() we can see it calls #nextOrSame() by adding 1 nanosecond to it:
#Nullable
public <T extends Temporal & Comparable<? super T>> T next(T temporal) {
return nextOrSame(ChronoUnit.NANOS.addTo(temporal, 1));
}
Unfortunately, #nextOrSame() is private and we can't call it. But we can "undo" the 1 nanosecond addition. So if we want to compare if a date matches a given cron, we could do something like:
CronExpression expression = CronExpression.parse("*/10 * 9-17 * * MON-FRI");
LocalDateTime testTime = LocalDateTime.of(2023, 1, 13, 10, 0, 0);
LocalDateTime truncatedTime = testTime.truncatedTo(ChronoUnit.SECONDS); // Truncate to seconds, as cronjobs run with seconds precision
LocalDateTime truncatedExpressionOffset = truncatedTime.minusNanos(1L); // Offsets the +1 in expression#next(), since #nextOrSame() is private.
LocalDateTime nextExpression = expression.next(truncatedExpressionOffset);
System.out.printf("Current time [%s] matches expression [%s]: [%s]", truncatedTime, expression, truncatedTime.equals(nextExpression));
If you play a bit with the timestamp (13th being a Friday):
Time [2023-01-13T10:00] matches expression [*/10 * 9-17 * * MON-FRI]: [true]
Time [2023-01-13T10:00:05] matches expression [*/10 * 9-17 * * MON-FRI]: [false]
Time [2023-01-12T09:00:20] matches expression [*/10 * 9-17 * * MON-FRI]: [true]
Time [2023-01-12T08:00:20] matches expression [*/10 * 9-17 * * MON-FRI]: [false]
Time [2023-01-14T09:00:20] matches expression [*/10 * 9-17 * * MON-FRI]: [false]
It's a bit of a workaround to "undo" the 1 nanosecond and call next(). But with some unit tests on this you can be prepared if internals do change when upgrading.

Related

Matching & Comparing Strings via Levenshtein Distance

I have one table with a static list of "template" strings, and another sheet that updates daily with new "populated" strings.
I want to be able to identify which "template" each string is based on by finding the string with the lowest distance, and then displaying the distance between the template and the new string as a percentile.
Is it possible to do a Levenshtein distance in Excel without having to resort to Macros?
I found this function for calculating the distance, but I'm a novice with this kind of code, and I'm not sure how to include the step for locating the closest match before displaying the distance. It also seems like this might not work for long strings (200+ characters) like I'm dealing with.
I'm a sheets guy, not normally a code guy, and I'm up against a brick wall here in terms of my understanding of what to do next. Thank you for your help!
It is possible to calculate the Levenshtein distance between two text strings using a named function such as ztiaa's LEVDIST.
But it may be more practical to use a custom function like the one you link to, or the following implementation that fuzzy matches values to a corpus using fuzzyset.js which is a JavaScript port of the Python fuzzyset.
/**
* Finds the closest matches to words using the FuzzySet library.
*
* #param {A2:A} words_to_find The text strings to find matches for.
* #param {Dictionary!W2:W} dictionary A list of words to match words_to_find against.
* #param {0.5} match_score_min Optional. A threshold value for how good the match must be. 1 means an exact match. The default is 0.33.
* #return {Array} The closest match to words_to_find found in the dictionary, or a blank value if there is no match.
* #customfunction
*/
function FindFuzzyMatch(words_to_find, dictionary, match_score_min) {
'use strict';
// version 1.2, written by --Hyde, 14 September 2022
// - hat tip to Andreas Muller
// - uses fuzzyset.js by Glen Chiacchieri, a port of fuzzyset by Mike Axiak
if (arguments.length < 2 || arguments.length > 3) {
throw `Wrong number of arguments to FindFuzzyMatch. Expected 2 or 3 arguments, but got ${arguments.length} arguments.`;
}
const words = Array.isArray(words_to_find) ? words_to_find : [[words_to_find]];
const dict = Array.isArray(dictionary) ? dictionary.flat() : [dictionary];
const fuzzyDictionary = FuzzySet(dict);
return words.map(row => row.map(word => {
if (!word) {
return null;
}
const fuzzyMatches = fuzzyDictionary.get(word, null, match_score_min);
return fuzzyMatches ? fuzzyMatches[0][1] : null; // get just the first result, ignoring its score
}));
}
// include https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js below,
// and remove the final export {} block

How do you ensure accuracy when dealing with ints and doubles within conditions?

Beginner here.
How does one ensure accuracy when dealing with small margins like this? one of my test cases results in 100.9 - which obviously isn't triggering the fee increase.
The floor division works for calculating the correct fee, but I'm not sure how to handle that preceding statement. Do I need to type cast every number to a double?
if ((Math.ceil(weightPerItemInOz * numberOfItems) / 16) > 100)
fee = fee * (Math.floor((double)(weightPerItemInOz * numberOfItems) / 1000)); ```

Get current system time in milliseconds

In Ruby, what is the right way to get the current system time since epoch(1970) in milliseconds?
I tried Time.now.to_i , it seems not the result I want. I need the result shows milliseconds and with long type, not float or double.
(Time.now.to_f * 1000).to_i
Time.now.to_f shows you the time including decimal numbers. To get number of miliseconds just multiply the time by 1000.
You can combine to_i and usec. The former returns the number of seconds since the Epoch, the latter returns the number of microseconds:
require 'time'
t = Time.at(1473152006, 2000)
t.to_i * 1000 + t.usec / 1000
#=> 1473152006002
This is equivalent to:
t.strftime('%s%L')
#=> "1473152006002"
In some cases like the above, to_f would introduce a slight floating point error:
t.to_f * 1000
#=> 1473152006001.9998
(t.to_f * 1000).to_i
#=> 1473152006001

Meaning of 1000L

I have a question on this code. what does the 1000L * 8L represents?
Example:
bytesRec += networkInterfaces[i].GetIPv4Statistics().BytesReceived / 1000L * 8L;
Sorry new to here
Thank you
Suffixes specify number types. They instruct the C# compiler that an integral literal such as 1000 be considered a certain type of number—for example, a long (1000L)

How to get running maximum in Stata?

I would like to get the running maximum by writing Stata code.
I think I am quite close:
gen ctrhigh`iv' = max(ctr, L1.ctr, L2.ctr, L3.ctr, ..., L`iv'.ctr)
As you can see, my data are time series and `iv' represents the window (e.g. 5, 10 or 200 days)
The only problem is that you cannot pass a varlist or string containing numbers to max. E.g. the following is not possible:
local ivs 5 10 50 100 200
foreach iv in `ivs' {
local vals
local i = 1
while (`i' <= `iv') {
vals "`vals' `i'"
local ++i
}
gen ctrhigh`iv' = max(varlist vals) //not possible
}
How would I achieve this instead?
Example of quickly computing a running standard deviation
* standard deviation of ctr, see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods *
gen ctr_sq = ctr^2
by tid: gen ctr_cum = sum(ctr) if !missing(ctr)
by tid: gen ctr_sq_cum = sum(ctr_sq) if !missing(ctr_sq)
foreach iv in $ivs {
if `iv' == 1 continue
by tid: gen ctr_sum = ctr_cum - L`iv'.ctr_cum if !missing(ctr_cum) & !missing(L`iv'.ctr_cum)
by tid: gen ctr_sq_sum = ctr_sq_cum - L`iv'.ctr_sq_cum if !missing(ctr_sq_cum) & !missing(L`iv'.ctr_sq_cum)
by tid: gen ctrsd`iv' = sqrt((`iv' * ctr_sq_sum - ctr_sum^2) / (`iv'*(`iv'-1))) if !missing(ctr_sq_sum) & !missing(ctr_sum)
label variable ctrsd`iv' "Rolling std dev of close ticker rank by `iv' days."
drop ctr_sum ctr_sq_sum
}
drop ctr_sq ctr_cum ctr_sq_cum
Note: this is not an exact sd, it's an approximation. I realize that this is very different from a maximum, but this may serve as an illustration on how to deal with large data computations.
Your example is time series data and implies that you have tsset the data. You don't say whether you also have panel or longitudinal structure. I will assume the worst and assume the latter as it doesn't make the code much worse. So, suppose tsset id date. In fact, that's irrelevant to the code here except to make explicit my assumption that id is an identifier and date a time variable.
An unattractive way to do this is to loop over observations. Suppose window is set to 42.
local window = 42
gen max = .
tsset id date
quietly forval i = 1/`=_N' {
su ctr if inrange(date, date[`i'] - `window', date[`i']) & id == id[`i'], meanonly
replace max = r(max) in `i'
}
So, in words as well: summarize values of ctr if date within window and it's in the same panel (same id), and put the maximum in the current observation.
The meanonly option is not well named. It calculates some other quantities besides the mean, and the maximum is one. But you do want the meanonly option to make summarize go as fast as possible.
See my 2007 paper on events in intervals, freely available at http://www.stata-journal.com/sjpdf.html?articlenum=pr0033
I say unattractive, but this approach does have the advantage that it is easy to work with once you understand it.
I am not setting up an expression with lots of arguments to max(). You said 200 as an example and nothing stated that you might not ask for more, so far as I can see there may be no upper limit on window length, but there will be a limit on how complicated that expression can be.
If I think of a better way to do it, I'll post it. Or someone else will....
It seems like I can pass a string of arguments to max, like so:
* OPTION 1: compute running max by days *
foreach iv in $ivs {
* does not make sense for less than two days *
if `iv' < 2 continue
di "computing running max for ctr interval `iv'"
* set high for this amount of days *
local vars "ctr"
forval i = 1 / `iv' {
local vars "`vars', L`i'.ctr"
}
by tid: gen ctrh`iv' = max(`vars')
}
* OPTION 2: compute running max by days, ensuring that entire range is nonmissing *
foreach iv in $ivs {
* does not make sense for less than two days *
if `iv' < 2 continue
di "computing running max for ctr interval `iv'"
* set high for this amount of days *
local vars "ctr"
local condition "!missing(ctr)"
forval i = 1 / `iv' {
local vars "`vars', L`i'.ctr"
local condition "`condition' & !missing(L`i'.ctr)"
}
by tid: gen ctrh`iv' = max(`vars') if `condition'
}
This computes very quickly and does exactly what I need.
However, if you need an arbitrarily large window I think you should resort to Nick's answer.

Resources