Time Function in Progress 4GL - openedge

I would like to insert 2 shift timings to the code.
(First Shift)
Shift starts from 8:00:00:000 to 19:59:59:999
(Second Shift)
Shift Starts from 20:00:00:000 to next day 7:59:59:999
I need to get the above exact data to be added to the below code.
Please help.
Below is the code:
IF TIME < (20 * 60 * 60) THEN DO:
ASSIGN StartDDT = dt_tm2dec(DATE(TODAY), 0)
EndDDT = dt_tm2dec(DATE(TODAY),19 * 60 * 60 + 59 * 60 + 59).
END.
ELSE DO:
ASSIGN StartDDT = dt_tm2dec(DATE(TODAY),20 * 60 * 60).
EndDDT = dt_tm2dec(DATE(TODAY + 1),07 * 60 * 60 + 59 * 60 + 59).
END.

The conditions you specified can be written as:
if ( time >= ( 8 * 60 * 60 )) and ( time < ( 20 * 60 * 60 )) then
do:
message "first shift".
end.
else
do:
message "second shift".
end.

You can use the DATETIME datatype to get millisecond accuracy on your times. Build the shift times with the DATETIME function, then compare your time to them. The NOW function gives you the current time down to the millisecond:
DEFINE VARIABLE dtShift1 AS DATETIME NO-UNDO.
DEFINE VARIABLE dtShift2 AS DATETIME NO-UNDO.
ASSIGN
dtShift1 = DATETIME(TODAY, (8 * 60 * 60 * 1000))
dtShift2 = DATETIME(TODAY, (20 * 60 * 60 * 1000)).
IF NOW >= dtShift1 AND NOW < dtShift2 THEN
MESSAGE "First shift" VIEW-AS ALERT-BOX INFORMATION.
ELSE
MESSAGE "Second shift" VIEW-AS ALERT-BOX INFORMATION.
You can also check the shift time for the following day by adding a day to TODAY:
dtShift1 = DATETIME(TODAY + 1, (8 * 60 * 60 * 1000))
And if you need to handle different time zones, use the DATETIME-TZ datatype.

Related

How to use or detect the character bits in hex value?

I take a hex or dec value and want to get its specific bits to write them on a display. For dec value, i can seperate bits one by one and write them with the code below. However, the code is for numbers, not for characters like A,B,C... in a hex value. Therefore, can someone help me about it? Even if i can detect the bit of a character, it will be enough because i can write that bits as a character
meas_value = 1100 // it works fine but for example meas_value = A010 it's not gonna work
digits[4] = (meas_value / 10000);
digits[3] = ((meas_value - (digits[4] * 10000)) / 1000);
digits[2] = ((meas_value - digits[4] * 10000
- digits[3] * 1000) / 100);
digits[1] = ((meas_value - digits[4] * 10000
- digits[3] * 1000 - digits[2] * 100)/10);
digits[0] = (meas_value - digits[4] * 10000
- digits[3] * 1000 - digits[2] * 100 - digits[1]*10);

Does moment duration() and humanize() handle small decimals?

Why does this, which I expect to output something like '18 mins'...
const shouldBe18Mins = moment.duration(0.00003408923868091461, 'years').humanize()
console.log(`Should be 18 mins: ${shouldBe18Mins}`)
... instead output a few seconds?
By my arithmetic, 0.00003408923868091461 * 365 * 24 * 60 = 17.918 mins.

Vigenère encryption in qbasic

How can I write a Vigenère encryption in Qbasic without the use of arrays?
I understand the math to encrypt a message:
Ca = Ma + Kb (mod 26)
And to decrypt a message:
Ma = Ca – Kb (mod 26).
I'm struggling with the syntax as I haven't found much information online.
You can solve this easily without using any arrays.
Below is my all-(Q)BASIC solution.
The MID$ function extracts one character from a string, and the ASC function converts the character into its ASCII code. Subtracting 65 produces a number in the range [0,25]. The encrypted number is turned back into a character using the CHR$ function. Hereafter the MID$ statement is used to put the encrypted character back in the string.
Because of the different lengths between the message and the encryption key, a separate iteration variable (j%) is needed to repeatedly walk through the key string.
msg$ = "ENCRYPTION"
PRINT msg$
key$ = "CLINTON"
k% = LEN(key$)
j% = 1
FOR i% = 1 TO LEN(msg$)
a% = (ASC(MID$(msg$, i%, 1)) - 65) + (ASC(MID$(key$, j%, 1)) -65)
MID$(msg$, i%) = CHR$(65 + a% + 26 * (a% > 25))
j% = j% + 1 + k% * (j% = k%)
NEXT i%
PRINT msg$
The above snippet could do without one - 65 and one + 65, but I've left these in for clarity.
The decryption process is quite similar. 3 little changes are all that it takes:
j% = 1
FOR i% = 1 TO LEN(msg$)
a% = (ASC(MID$(msg$, i%, 1)) - 65) - (ASC(MID$(key$, j%, 1)) -65)
MID$(msg$, i%) = CHR$(65 + a% - 26 * (a% < 0))
j% = j% + 1 + k% * (j% = k%)
NEXT i%
PRINT msg$
Running both snippets in a row produces:
ENCRYPTION
GYKERDGKZV
ENCRYPTION
What about a version of the code that can deal with spaces, punctuation marks, and accented characters?
The code is very similar and even a bit simpler:
msg$ = "This is any text that needs encrypting. So sayeth Sep Roland!"
PRINT msg$
key$ = "Blaise de Vigenère"
k% = LEN(key$)
j% = 1
FOR i% = 1 TO LEN(msg$)
a% = ASC(MID$(msg$, i%, 1)) + ASC(MID$(key$, j%, 1))
MID$(msg$, i%) = CHR$(a% + 256 * (a% > 255))
j% = j% + 1 + k% * (j% = k%)
NEXT i%
PRINT msg$
j% = 1
FOR i% = 1 TO LEN(msg$)
a% = ASC(MID$(msg$, i%, 1)) - ASC(MID$(key$, j%, 1))
MID$(msg$, i%) = CHR$(a% - 256 * (a% < 0))
j% = j% + 1 + k% * (j% = k%)
NEXT i%
PRINT msg$
I will not reproduce any output here because that would be a real pita...
Are these strange embedded conditions correct?
(a% + 26 * (a% > 25))
Consider the equivalent simple code:
IF a% > 25 THEN
a% = a% - 26
ENDIF
If the a% variable is greater than 25, we need to subtract 26.
Nonetheless the (a% + 26 * (a% > 25)) form uses addition.
This so happens because a TRUE condition evaluates to -1.
If a% > 25 is TRUE we get (a% + 26 * -1) -> a% - 26
If a% > 25 is FALSE we get (a% + 26 * 0) -> a%
You can simply get the ASCII value of the char as a number and then subtract the character value of A. You would get a number in the range [0, 26). Then you'd perform encryption / decryption as you've stated. To get back a valid character value then reverse and add the value of A. This works because the letters of the English alphabet (the ABC) are listed in order in ASCII.
To get the ciphertext or plaintext simply iterate over all the characters in the string (possibly after checking that it doesn't contain any other characters) and append the encrypted / decrypted character to a new string, and finally return that. Viola, no arrays, just strings, characters and numerical values.
That's all folks.

how to get modulo of a value in exponential form

Question is about the modulo operator on very large numbers.
For example consider a question where the total number of permutations are to be calculated.
Consider a number of 90 digits with each of the 9 numbers (1 to 9) repeating 10 times
so 90!/(10!)^9) is to be calculated
After reading many answers on StackOverflow I used logarithms to do it.
Now consider the log value to be 1923.32877864.
Now my question is how can I display the answer (i.e. 10 ^ log10(value) ) modulo of "m"?
And is this the best method for calculating the possible number of permutations?
Edit
Got the solution :)
Thanks to duedl0r.
Did it the way you specified using Modular Multiplicative Inverse.Thanks :)
I'm not sure whether this is actually possible and correct, but let me summarize my comments and extend the answer from Miky Dinescu.
As Miky already wrote:
a × b ≣m am × bm
You can use this in your equality:
90! / 10!^9 ≣m x
Calculate each term:
90!m / 10!^9m ≣m x
Then find out your multiplicative inverse from 10!^9m. Then multiplicate the inverse with 90!m.
update
This seems to be correct (at least for this case :)). I checked with wolfram:
(90!/10!^9) mod (10^9+7) = 998551163
This leads to the same result:
90! mod (10^9+7) = 749079870
10!^9 mod (10^9+7) = 220052161
do the inverse:
(220052161 * x) mod(10^9+7) = 1 = 23963055
then:
(749079870*23963055) mod (10^9+7) = 998551163
No proof, but some evidence that it might work :)
I would argue that the way to compute the total number of permutations modulo m, where m is an arbitrary integer (usually chosen to be a large prime number) is to use the following property:
(a * b) % m = ((a % m) * (b % m)) % m
Considering that the total number of permutations of N is N! = 1 * 2 * 3 * .. * N, if you need to compute N! % m, you can essentially apply the property above for multiplication modulo m, and you have:
((((1 * (2 % m)) % m) * (3 % m)) % m) * ..
EDIT
In order to compute the 90! / (10! ^ 9) value you could simplify the factors and then use multiplication modulo m to compute the final result modulo m.
Here's what I'm thinking:
90! = 10! * (11 * 12 * .. * 20) * (21 * 22 * .. * 30) * .. * (81 * 82 * .. * 90)
You can then rewrite the original expression as:
(10! * (11 * 12 * .. * 20) * (21 * 22 * .. * 30) * .. * (81 * 82 * .. * 90)) / (10! * 10! * ... * 10!)
At the numerator, you have a product of 9 factors - considering each expression in parenthesis a factor. The same is true for the denominator (you have 9 factors, each equal to 10!).
The first factor at the denominator is trivial to simplify. After that you still have 8 pairs that need simplification.
So, you can factor each term of the products and simplify the denominator away. For example:
11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 <=> 11 * 2 * 2 * 3 * 13 * 2 * 7 * 3 * 5 * 2 * 2 * 2 * 2 * 17 * 2 * 9 * 2 * 2 * 5
The denominator will always be: 2 * 3 * 2 * 2 * 5 * 2 * 3 * 7 * 2 * 2 * 2 * 2 * 3 * 3 * 2 * 5
After the simplification the second pair reduces to : 2 * 2 * 11 * 13 * 17 * 19
The same can be applied to each subsequent pair and you will end up with a simple product that can be computed modulo m using the formula above.
Of course, efficiently implementing the algorithm to perform the simplification will be tricky so ultimately there has to be a better way that eludes me now.

Convert unix timestamp to julian

How can I convert from a unix timestamp (say 1232559922) to a fractional julian date (2454853.03150).
I found a website ( http://aa.usno.navy.mil/data/docs/JulianDate.php ) that performs a similar calculation but I need to do it programatically.
Solutions can be in C/C++, python, perl, bash, etc...
The Unix epoch (zero-point) is January 1, 1970 GMT. That corresponds to the Julian day of 2440587.5
So, in pseudo-code:
function float getJulianFromUnix( int unixSecs )
{
return ( unixSecs / 86400.0 ) + 2440587.5;
}
I know that this is an old post, but I'll just say ...
The answer given by Jason Cohen is a good approximation of the conversion.
There is a problem though that relates to the number of seconds in one day. A day is not -exactly- 86400 seconds long, and periodically seconds are added to days in order to keep time synchronized with the various observable standards. These are called Leap Seconds (https://en.wikipedia.org/wiki/Leap_second). Leap seconds are added to UTC in order to keep it within 1 second of UT1.
It stands to reason that as more and more time has elapsed since Jan 1, 1970, the simple conversion above will accrue more and more error from "actual observable time." Between 1972 and 2013 there were added 25 leap seconds.
Part of the beauty and the simplicity of Julian Day numbers is that they don't represent date strings at all. They are just a count of elapsed time since the start of the Julian Epoch, much like POSIX time is a continuous count of milliseconds since the POSIX Epoch. The only problem that exists, then, is when you try to map a Julian Day number to a localized date string.
If you need a date string that is accurate to within a minute (in 2013), then you'll need an algorithm that can account for leap seconds.
Here is my JavaScript code to convert Unix timestamp to Julian. Originally is showing the current date and time, but with a little mod is answer to your question:
function computeJulianDate(DD,MM,YY,HR,MN,SC) {
with (Math) {
HR = HR + (MN / 60) + (SC/3600);
GGG = 1;
if (YY <= 1585) GGG = 0;
JD = -1 * floor(7 * (floor((MM + 9) / 12) + YY) / 4);
S = 1;
if ((MM - 9)<0) S=-1;
A = abs(MM - 9);
J1 = floor(YY + S * floor(A / 7));
J1 = -1 * floor((floor(J1 / 100) + 1) * 3 / 4);
JD = JD + floor(275 * MM / 9) + DD + (GGG * J1);
JD = JD + 1721027 + 2 * GGG + 367 * YY - 0.5;
JD = JD + (HR / 24);
}
return JD;
}
function getUTCDateTimeOrJD(now,jd=0) {
var hours = now.getUTCHours();
var minutes = now.getUTCMinutes();
var seconds = now.getUTCSeconds()
var month = now.getUTCMonth() + 1;
var day = now.getUTCDate();
var year = now.getUTCFullYear();
if (jd==1)
return computeJulianDate(month, day, year, hours, minutes, seconds);
else
return day+". "+month+". "+year+". "+hours+":"+minutes+":"+seconds;
}
var unixTime = 1473294606;
getUTCDateTimeOrJD(new Date(unixTime*1000));
getUTCDateTimeOrJD(new Date(unixTime*1000),1);
Working JSFiddle example here
This question was asked over 13 years ago as of writing. That's pretty wild. Thanks to eapo's JS formula I converted it to PineScript v5 and in testing its at least really close. I don't think perfect accuracy would even be relevant for most (if any) TradingView applications. So, I didn't go as far as to ensure perfect accuracy. But it works. Thanks eapo, you saved me a bunch of time.
EDIT: TradingView displays times in the stock/currency exchange time zone. So, it became necessary to create additional arguments to provide for the UTC offsets that exchanges utilize.
[IMPORTANT: Keep in mind that exchanges that utilize daylight savings time will shift from UTC - n to UTC - n - 1 depending on the DST state. You must update your UTC offset argument accordingly.]
// Julian Date & Partial Day in CST
computeJulianDate(dd, mm, yy, hr, mn, sc, offset=0, live=false) =>
HR = hr
HR := hr + (mn / 60) + (sc / 3600)
GGG = 1
if year <= 1585
GGG := 0
float JD = -1 * math.floor(7 * (math.floor((mm + 9) / 12) + yy) / 4)
S = 1
if ((mm - 9)<0)
S :=-1
A = math.abs(mm - 9)
J1 = math.floor(yy + S * math.floor(A / 7))
J1 := -1 * math.floor((math.floor(J1 / 100) + 1) * 3 / 4)
JD := JD + math.floor(275 * mm / 9) + dd + (GGG * J1)
JD := JD + 1721027 + 2 * GGG + 367 * yy
JD := JD + (HR / 24)
barsInSession = timeframe.isintraday ? ((24 * 60) / timeframe.multiplier) : timeframe.multiplier
barsInSession := math.floor(barsInSession) == barsInSession and timeframe.isintraday ? barsInSession - 1 : math.floor(barsInSession)
offsetInc = 1 / barsInSession
offsetCt = (offset * ((barsInSession / 24) * offsetInc))
JD := live ? JD + offsetCt : math.floor(JD - offsetCt) - 0.5
JD

Resources