How do I convert a decimal number representing time to actual time in Crystal Reports 2008? Ex: "1.5" represents 1:30 - crystal-reports

I'm trying to edit an existing Crystal Report that shows time allowances for work orders. Budgeted Time / Actual Time / Remaining Time type deal.
These fields show up as not properly converting time from the data field for the report. The person who made the report has some formula for it already but I'm not sure what's it doing.
Formula: Standard Time
Stringvar array Std_Time := split(replace(cstr({WOMNT_CARD.STANDARD_HOURS_DURATION}),",",""),".");
val(Std_Time[1])*60+val(Std_Time[2])
The field used in the report is Sum of #Standard Time (Number).
How do I fix this so these numbers are properly converted?

The formula that you have posted does the following:
First it converts the datatype of the {WOMNT_CARD.STANDARD_HOURS_DURATION} field to string by using the cstr function, the result is being stripped of commas with the replace function and the resulted string is being split into an array by using the dot character as the delimiter.
So, for the value 1.5 the Std_Time variable will hold the following
Std_Time[1] → 1
Std_Time[2] → 5
Finally it calculates the result by multiplying the first value of the first index with 60 and adds to it the value of the second index. The value 1.5 becomes 1 * 60 + 5 = 65
If the 1.5 must represent 1:30 then the last line must become
val(Std_Time[1]) * 60 + 60 * val(Std_Time[2]) / 10
because 60 * 5 / 10 = 30
or you can use for simplicity just the following
60 * val(replace(cstr({WOMNT_CARD.STANDARD_HOURS_DURATION}),",",""))
since 60 * 1.5 = 90

Related

Why is the range of the timestamp type 4713 BC to 294276 AD?

Postgresql has a timestamp datatype with resolution 1 microsecond and range 4713 BC to 294276 AD that takes up 8 bytes (see https://www.postgresql.org/docs/current/datatype-datetime.html).
I have calculated the total number of microseconds in that range as (294276 + 4713) × 365.25 × 24 × 60 × 60 × 1000000 = 9.435375266×10¹⁸. This is less than 2⁶⁴ = 1.844674407×10¹⁹, but also more than 2⁶³ = 9.223372037×10¹⁸.
I might be off by a few days due to calendar weirdness and leap years, but I don't think it's enough to push the number below 2⁶³.
So, why were the limits chosen like that? Why not use the full range available with 64 bits?
The internal representation of timestamps is in microseconds since 2000-01-01 00:00:00, stored as an 8-byte integer. So the maximum possible year would be something like
SELECT (2::numeric^63 -1) / 365.24219 / 24 / 60 / 60 / 1000000 + 2000;
?column?
═════════════════════════
294277.2726976055146158
(1 row)
which explains the upper limit.
The minimum is explained by a comment in src/include/datatype/timestamp.h:
/*
* Range limits for dates and timestamps.
*
* We have traditionally allowed Julian day zero as a valid datetime value,
* so that is the lower bound for both dates and timestamps.
*
* The upper limit for dates is 5874897-12-31, which is a bit less than what
* the Julian-date code can allow. For timestamps, the upper limit is
* 294276-12-31. The int64 overflow limit would be a few days later; again,
* leaving some slop avoids worries about corner-case overflow, and provides
* a simpler user-visible definition.
*/
So the minimum is taken from the lower limit on Julian dates.

Pine scripting: how to find the price X days ago

In Pine Script, how do I find the price based on a certain number of days ago? I've tried something like this...
// Find the price 90 days ago
target = time - 90 * 60 * 60 * 24 * 1000
valuewhen(time < target, close, 1)
...however time < target never seems to return true – presumably because the current bar's time cannot also be in the past at the same time. Perhaps valuewhen() wasn't designed to be used with dynamic values that change on every bar?
Do I need to use a loop instead, and scan through every past bar until I find the date I'm looking for?
Perhaps there's a better way, but the workaround I'm using currently using is a function with a for loop, scanning backwards until the appropriate date is found. Here is my function:
priceXDaysAgo(numDays) =>
targetTimestamp = time - numDays*60*60*24*1000
// Declare a result variable with a "void" value
float result = if false
1
// We'll scan backwards through the preceding bars to find the first bar
// earlier than X days ago (it might be a little greater than X days if
// there was a break in trading: weekend, public holiday, etc.)
for i = 1 to 1000
if time[i] < targetTimestamp
result := close[i]
break
result
You can then call the function anywhere in your script:
priceXDaysAgo(90)

Limits of string transformations in q, stars in TOK

I'm trying to convert int values to minutes, and in some cases it gives me stars * in the result:
string "U"$"99:59" / "99:59"
string "U"$"100:00" / "**:00"
What are the rules for this stars to appear?
Update for seconds:
string "V"$"1000" / "10:00:00"
string "V"$"10000" / "**:00:00"
string "V"$"100000" / "10:00:00"
string "V"$"1000000" / "**:00:00"
Is it possible to configure this rules, say to stop smudging the origin values?
I think the stars that appear are just kdb's way of saying that the result couldn't be displayed.
The minute and second datatypes have the form hh:mm and hh:mm:ss, respectively. So if kdb reads the hour part as having more than 3 digits (i.e greater than 99), the stars will appear.
If you're casting a string into a minute datatype, then kdb converts the last two chars into minutes, and the rest into hours, eg
"U"$"1234" / 12:34
"U"$"12345" / **:45
Something similar occurs when you convert a string into seconds. If the length of the string is 6 or greater, then the last two chars are converted into seconds. Otherwise, the seconds are set to 00. The rest of the string is then converted into hh:mm as above. To illustrate this, look at:
"V"$"1234" / 12:34:00
"V"$"12345" / **:45:00
"V"$"123456" / 12:34:56
"V"$"1123456" / **:34:56
I should also note that even though stars appear, you can still do things like temporal arithmetic as usual, eg
"U"$"100:00 / **:00
("U"$"100:00")-"U"$"1:00" / 99:00

timestamp to milliseconds conversion around midnight getting messed up

I am using following function to convert timestamp in format (e.g.) 02:49:02.506 to milliseconds in perl.
sub to_millis {
my( $hours, $minutes, $seconds, $millis) = split /:/, $_[0];
$millis += 1000 * $seconds;
$millis += 1000 * 60 * $minutes;
$millis += 1000 * 60 * 60 * $hours;
return $millis;
}
I am then using the milliseconds generated from above routine to calculate the time difference between two timestamps in milliseconds. This works fine all day but gets messed up around midnight, when the timestamp changes to 00:00:00.000. So any logs generated for 1 hr (between 12am to 1am) gets me values in negative for the timestamp difference. Since my timestamp doesn't have a date in it, how do I fix this problem? I am trying to do this on a mobile device, which doesn't have many perl modules installed. So I don't have the liberty of using all the perl modules available.
If you know the ordering of your two timestamps, and if you know that they're no more than 24 hours apart, if you get a negative difference add 24 hours (86,400,000 milliseconds).
If you don't have that information, then you won't be able to distinguish between a 2-minute span and a span of 24 hours and 2 minutes.
I assume that your timestamps will never be more than 23 hours 59 minutes apart?
Let's take two time stamps A and B. I am assuming that A happens before B.
Normally, if A is less than B, I know I can get my time by subtracting A from B. However, in this case, A is bigger than B. I now have to assume that I've wrapped around midnight. What do I do?
I know that the difference between A and B is A going to midnight, PLUS B.
For example, A is 11:58:30 and B is 00:02:00
I know that A will be 90 seconds before midnight, and B will add another 120 seconds to that time. Thus, the total difference will be 90 + 120 = 210 seconds.
Using your routine:
my $midnight = to_millis( "23:59:00:000" ); # Need the time at midnight
my $a_time = to_millis( $a_timestamp );
my $b_time = to_millis( $b_timestamp );
my $time_diff;
if ( $a_time < $b_time ) { # Normal timestamp issue
$time_diff = $b_time - $a_time;
}
else { # We wrapped around midnight!
my $first_part = $midnight - $a_time; # Time from A to midnight
$time_diff = $first_part + $b_time # We add the time from midnite to B
}
You have two timestamps, A and B. If B is always conceptually "after" A but the interval from A to B could cross a date boundary, then do
if (B < A) B+=86400000
and then do the subtraction. Or equivalently
diff = B - A
if (diff < 0) diff+=86400000
If, however you are not guaranteed that B will always be "after" A, you have to decide what is the acceptable range of positive and negative values for the difference. If it's more than half a day you're out of luck, there's no way to solve the problem as you cannot tell if a negative interval represents a real negative interval or a positive one that happened to cross a day boundary.
To handle the wrap around at midnight:
$elapsed_ms = $t2_ms - $t1_ms;
if ($elapsed_ms < 0) $elapsed_ms += (24 * 60 * 60 * 1000);

subtracting one from another in matlab

My time comes back from a database query as following:
kdbstrbegtime =
09:15:00
kdbstrendtime =
15:00:00
or rather this is what it looks like in the command window.
I want to create a matrix with the number of rows equal to the number of seconds between the two timestamps. Are there time funcitons that make this easily possible?
Use datenum to convert both timestamps into serial numbers, and then subtract them to get the amount of seconds:
secs = fix((datenum(kdbstrendtime) - datenum(kdbstrbegtime)) * 86400)
Since the serial number is measured in days, the result should be multiplied by 86400 ( the number of seconds in one day). Then you can create a matrix with the number of rows equal to secs, e.g:
A = zeros(secs, 1)
I chose the number of columns to be 1, but this can be modified, of course.
First you have to convert kdbstrendtime and kdbstrbegtime to char by datestr command, then:
time = datenum(kdbstrendtime )-datenum(kdbstrbegtime )
t = datestr(time,'HH:MM:SS')