Strange Date Format in XML, Convert to Ruby DateTime Object - ruby

This is a tough one to google for. I have an XML document that's a million lines long, and I'm using Ruby to parse it and remove entries I don't care about. One my my criteria is the date created. These XML blocks have funny looking dates in them
<attribute name="datemodified" type="date">362895460.21263897418975830078</attribute>
<attribute name="datecreated" type="date">356831173.15324598550796508789</attribute>
I've never seen dates formatted like that exactly. They look similar to if you did something like Time.now.to_f. Even so I don't know how I'd turn those into Ruby DateTime objects. If you can even identify how these times are created, or what they mean, that would be super helpful.
If it helps, this XML file was originally created by a Mac OS X application known as "Things".
Thanks for reading!
Update: I've created two more entries and recorded the times at which i created them:
From JULY-02-2012 9:57 AM
<attribute name="datemodified" type="date">362941035.01687598228454589844</attribute>
<attribute name="datecreated" type="date">362940986.89370900392532348633</attribute>
From JULY-02-2012 9:58 AM
<attribute name="datemodified" type="date">362941107.69538801908493041992</attribute>
<attribute name="datecreated" type="date">362941080.53793197870254516602</attribute>
I couldn't get down to the second on accuracy, but i did make them about minute apart... Which makes it seem that these are in fact seconds... But... from some random date. Maybe the developer's birthday :)
Doing some quick math, it would appear that the randomish date is right around 2000-12-31 16:09:43 -0800, or perhaps 01/01/01, for ease of memory... And 978336000 in seconds.

The Time.at method translates from seconds since 1970 to a Time instance:
[1] pry(main)> Time.at 362895460.21263897418975830078
=> 1981-07-02 00:17:40 -0400
If that date isn't right, but the units are seconds, you could add a constant to get to the correct date, e.g.
[2] pry(main)> Time.parse('2001-01-01') - Time.at(0)
=> 978325200.0

The numbers look to me like the integer part is a Julian date and the fraction part is the fraction of a day. I haven't investigated that in detail. For reference the code in Saxon for converting date/time from "Julian instant" is:
public static DateTimeValue fromJulianInstant(/*#NotNull*/ BigDecimal instant) {
BigInteger julianSecond = instant.toBigInteger();
BigDecimal microseconds = instant.subtract(new BigDecimal(julianSecond)).multiply(DecimalValue.BIG_DECIMAL_ONE_MILLION);
long js = julianSecond.longValue();
long jd = js / (24L * 60L * 60L);
DateValue date = DateValue.dateFromJulianDayNumber((int)jd);
js = js % (24L * 60L * 60L);
byte hour = (byte)(js / (60L * 60L));
js = js % (60L * 60L);
byte minute = (byte)(js / (60L));
js = js % (60L);
return new DateTimeValue(date.getYear(), date.getMonth(), date.getDay(),
hour, minute, (byte)js, microseconds.intValue(),0 , true);
}
plus
public static DateValue dateFromJulianDayNumber(int julianDayNumber) {
if (julianDayNumber >= 0) {
int L = julianDayNumber + 68569 + 1; // +1 adjustment for days starting at noon
int n = (4 * L) / 146097;
L = L - (146097 * n + 3) / 4;
int i = (4000 * (L + 1)) / 1461001;
L = L - (1461 * i) / 4 + 31;
int j = (80 * L) / 2447;
int d = L - (2447 * j) / 80;
L = j / 11;
int m = j + 2 - (12 * L);
int y = 100 * (n - 49) + i + L;
return new DateValue(y, (byte) m, (byte) d, true);
} else {
// add 12000 years and subtract them again...
DateValue dt = dateFromJulianDayNumber(julianDayNumber +
(365 * 12000 + 12000 / 4 - 12000 / 100 + 12000 / 400));
dt.year -= 12000;
return dt;
}
}

Related

BeanShell PreProcessor (JMeter) - How can I generate a random future DateTime Stamp that covers current time out to 7 days?

I need assistance. I got some of this code off another site. It was randomly generating a date for the previous 7 days and randomly generating an hour and minute within a 24 hour period (any). I need the opposite of sorts. I need a random time that covers the current "now" time and goes forward 7 days but also requires the time (hour and minute) to be within a set hour range.
Requirements
Random Date covering current day ("now") and ahead one week (7 days).
Random Time generated; however time must fall between the hours of 1000hrs to 2200hrs and formatted as ("yyyy-MM-dd'T'HH:mm:ss").
My BS PreProcessor Parameters I was passing for the below code are (1 5 5). My dates seem to generate just fine but my time is only generating random hours as hours within the next 5 hours. How can I set a time range of 10am-10pm?
import java.text.SimpleDateFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.Random;
int minDay = Integer.parseInt(bsh.args[0]); // get first parameter minimal X Days ahead
int maxDay = Integer.parseInt(bsh.args[1]); // get second parameter maximal X Days ahead
int maxMinutesActivity = Integer.parseInt(bsh.args[2]); // get maximal duration of activity
int myThreadNum = 0;
int randomDay = 0; // RandomDays ahead
int minHour = 0;
int maxHour = 5;
int randomHour = 0;
int minMinute = 0;
int maxMinute = 60;
int randomMinute = 0;
int randomMinuteDuration = 0;
String formattedDate = "";
Random randomvar = new Random();
Date datevar = new Date();
Date datevarThisWeek = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
NumberFormat myFormat = NumberFormat.getInstance();
myFormat.setMinimumIntegerDigits(2); // required to have minimal two digits for Day, Hour, Minute
myThreadNum = ${__threadNum}; // just to show the thread number in debug
vars.put("myThreadNum",myFormat.format(myThreadNum));
randomDay = minDay+randomvar.nextInt(maxDay-minDay+1); // randomDays ahead between minDay and maxDay
datevar.setDate(datevar.getDate() - randomDay );
vars.put("randomDay",myFormat.format(randomDay));
randomHour = 1+randomvar.nextInt(maxHour-minHour+1); // randomHour ahead between minHour and maxHour
vars.put("randomHour",myFormat.format(randomHour));
randomMinute = minMinute+randomvar.nextInt(maxMinute-minMinute+1); // randomHour ahead between minMinute and maxMinute
vars.put("randomMinute",myFormat.format(randomMinute));
randomMinuteDuration = maxMinutesActivity; // randomduration between 1 and maxMinutesActivity
vars.put("randomMinuteDuration",myFormat.format(randomMinuteDuration));
// Calculate a Start and End time for this Week
randomDay = 1+randomvar.nextInt(5-1+1); // randomDays ahead this Week
datevarThisWeek.setDate(datevarThisWeek.getDate() + randomDay );
datevarThisWeek.setTime(datevarThisWeek.getTime() + ((randomMinute + (randomHour * 60 )) * 60 * 1000 ));
//datevarThisWeek.setTime(datevarThisWeek.getTime() + ((randomMinute + (randomHour * 60 )) * 60 * 1000 ) + myThreadNum );
formattedDate = df.format(datevarThisWeek);
vars.put("randomFireTime_FUTURE",formattedDate);
datevarThisWeek.setTime(datevarThisWeek.getTime() + (randomMinuteDuration * 60 * 1000 ));
//datevarThisWeek.setTime(datevarThisWeek.getTime() + (randomMinuteDuration * 60 * 1000 ) + myThreadNum );
formattedDate = df.format(datevarThisWeek);
vars.put("randomOrderTime_FUTURE",formattedDate);
Java fake library Might helps you.
import com.github.javafaker.Faker;
Date dob= faker.date().between(date1,date2);

work out how many seconds have expired in total during game play

~Why the hell has this had down votes.... you people are weird!
Ok so this is a very simply HTML5 and jQuery and PHP game. Sorry to the people who have answered, I forgot to say this is a php script, i have updated here to reflect.
the first level takes 1 minute. Every level after that takes an extra 10 seconds than the last level. like so;
level 1 = 60 seconds
level 2 = 70 seconds
level 3 = 80 seconds
level 4 = 90 seconds
and so on infinitely.
I need an equation that can figure out what is the total amount of seconds played based on the users level.
level = n
i started with (n * 10) + (n * 60) but soon realized that that doesn't account for the last level already being 10 seconds longer than the last. I have temporarily fixed it using a function calling a foreach loop stopping at the level number and returning the value. but i really want an actual equation.
SO i know you wont let me down :-)
Thanks in advance.
this is what i am using;
function getnumberofsecondsfromlevel($level){
$lastlevelseconds = 60;
while($counter < $level){
$totalseconds = $lastlevelseconds+$totalseconds;
$lastlevelseconds = $lastlevelseconds + 10;
$counter++;
}
return $totalseconds;
}
$level = $_SESSION['**hidden**']['thelevel'];
$totaldureationinseconds = getnumberofsecondsfromlevel($level);
but i want to replace with an actual equation
like so;(of course this is wrong, this is just the example of the format i want it in i.e an equation)
$n = $_SESSION['**hidden**']['thelevel']; (level to get total value of
in seconds)
$s = 60; (start level)
$totaldureationinseconds = ($n * 10) + ($s * $n);
SOLVED by Gopalkrishna Narayan Prabhu :-)
$totalseconds = 60 * $level + 5* (($level-1) * $level);
var total_secs = 0;
for(var i = 1; i<= n ;i++){
total_secs = total_secs + (i*10) + 50;
}
for n= 1, total_secs = 0 + 10 + 50 = 60
for n= 2, total_secs = 60 + 20 + 50 = 130
and so on...
For a single equation:
var n = level_number;
total_secs = 60 * n + 5* ((n-1) * n);
Hope this helps.
It seems as though you're justing looking for the equation
60 + ((levelN - 1) * 10)
Where levelN is the current level, starting at 1. If you make the first level 0, you can get rid of the - 1 part and make it just
60 + (levelN * 10)
Thought process:
What's the base/first number? What's the lowest it can ever be? 60. That means your equation will start with
60 + ...
Every time you increase the level, you add 10, so at some point you'll need something like levelN * 10. Then, it's just some fiddling. In those case, since you don't add any on the first left, and the first level is level 1, you just need to subtract 1 from the level number to fix that.
You can solve this with a really simple mathematical phrase (with factorial).
((n-1)! * 10) + (60 * n)
n is the level ofcourse.

EQUALOP error message with SML

I am trying to create a simple function that takes two dates of format int*int*int and return if the first one is older than the second or not.
fun is_older (date1: (int*int*int), date2: (int*int*int)) =
val in_days1 = (#1 (date1) * 365) + (#2 (date1) * 30) + #3 date1;
val in_days2 = (#1 (date2) * 365) + (#2 (date2) * 30) + #3 date1;
if in_days1 < in_days2
then true
else false
I get this error:
hwk_1.sml:1.53 Error: syntax error: inserting EQUALOP
uncaught exception Compile [Compile: "syntax error"]
raised at: ../compiler/Parse/main/smlfile.sml:15.24-15.46
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:296.17-296.20
Can anyone help please?
In addition to what has already been mentioned, you also ought to use pattern matching to decompose that 3-tuple. Doing this, you can also throw away the type annotations, as it is now clear that this is a 3-tuple (both for the reader, but more importantly also the type system).
fun is_older ((y1, m1, d1), (y2, m2, d2)) =
let
val days1 = y1 * 365 + m1 * 30 + d1
val days2 = y2 * 365 + m2 * 30 + d2
in
days1 < days2
end
However you could do this a bit smarter. If you have multiple functions working with dates, you could create a nice little helper function toDays. In the below example i have just included inside the isOlder function, but you could put it at top level or inside a local-declaration if you wan't to hide it away
fun isOlder (date1, date2) =
let
fun toDays (y, m, d) = y * 365 + m * 30 + d
in
toDays date1 < toDays date2
end
val in_days1 = (#1 (date1) * 365) + (#2 (date1) * 30) + #3 date1;
val in_days2 = (#1 (date2) * 365) + (#2 (date2) * 30) + #3 date1;
Local val definitions need to be between let and in.
FWIW, I got the same error on one of the other exercises in this same homework:
Error: syntax error: inserting EQUALOP
but in my case, it was happening on the first line. This was confusing to me, because I'm coming from Python, where the error usually happens after the mistake.
Bottom line, and the thing I wanted to know is this: this error means it can't compile the code as written.
P.S. if you use let and in you also have to use end. (You didn't need to use val or let to solve the is_older problem - there is a way to do it with set logic alone).
it worked for me:
fun is_older(diaUno : (int * int * int), diaDos : (int * int * int)) =
let
fun setDayNum(diaUno : (int * int * int)) =
let
val diaUnoInt = (#1 (diaUno) * 365) + (#2 (diaUno) * 30) + #3 diaUno
in
diaUnoInt
end
val dia1 = setDayNum(diaUno)
val dia2 = setDayNum(diaDos)
in
if dia1 < dia2 then diaUno else diaDos
end

Algorithm needed to calculate difference between two times

I have an hour selection drop down 0-23 and minutes selection drop down 0-59 for Start time and End time respectively (so four controls).
I'm looking for an algorithm to calculate time difference using these four values.
Since they're not stored in fancy date/time selection controls, I don't think I can use any standard date/time manipulation functions.
How do I calculate the difference between the two times?
This pseudo-code gives you the algorithm to work out the difference in minutes. It assumes that, if the start time is after the end time, the start time was actually on the previous day.
const MINS_PER_HR = 60, MINS_PER_DAY = 1440
startx = starthour * MINS_PER_HR + startminute
endx = endhour * MINS_PER_HR + endminute
duration = endx - startx
if duration < 0:
duration = duration + MINS_PER_DAY
The startx and endx values are the number of minutes since midnight.
This is basically doing:
Get number of minutes from start of day for start time.
Get number of minutes from start of day for end time.
Subtract the former from the latter.
If result is negative, add number of minutes in a day.
Don't be so sure though that you can't use date/time manipulation functions. You may find that you could easily construct a date/time and calculate differences with something like:
DateTime startx = new DateTime (1, 1, 2010, starthour, startminute, 0);
DateTime endx = new DateTime (1, 1, 2010, endhour , endminute , 0);
Integer duration = DateTime.DiffSecs(endx, startx) / 60;
if (duration < 0)
duration = duration + 1440;
although it's probably not needed for your simple scenario. I'd stick with the pseudo-code I gave above unless you find yourself doing some trickier date/time manipulation.
If you then want to turn the duration (in minutes) into hours and minutes:
durHours = int(duration / 60)
durMinutes = duration % 60 // could also use duration - (durHours * 60)
This will compute duration in minutes including the year as factor
//* Assumptions:
Date is in Julian Format
startx = starthour * 60 + startminute
endx = endhour * 60 + endminute
duration = endx - startx
if duration <= 0:
duration = duration + 1440
end-if
if currday > prevday
duration = duration + ((currday-preday) - 1 * 1440)
end-if
First you need to check to see if the end time is greater than or equal to the start time to prevent any problems. To do this you first check to see if the End_Time_Hour is greater than Start_Time_Hour. If they're equal you would instead check to see if End_Time_Min is greater than or equal to Start_Time_Min.
Next you would subtract Start_Time_Hour from End_Time_Hour. Then you would subtract Start_Time_Min from End_Time_Min. If the difference of the minutes is less than 0 you would decrement the hour difference by one and add the minute difference to 60 (or 59, test that). Concat these two together and you should be all set.
$start_time_hr = 5;
$start_time_mi = 50;
$end_time_hr = 8;
$end_time_mi = 30;
$diff = (($end_time_hr*60)+$end_time_mi) - (($start_time_hr*60)+$start_time_mi);
$diff_hr = (int)($diff / 60);
$diff_mi = (int)($diff) - ($diff_hr*60);
echo $diff_hr . ':' . $diff_mi;
simple equation should help:
mindiff = 60 + endtime.min - starttime.min
hrdiff = ((mindiff/60) - 1) + endtime.hr - starttime.hr
This gives you the duration in hours and minutes
h1 = "hora1"
m1 "min1"
h2 "hora2"
m2 = "min2"
if ( m1 > m2)
{
h3 = (h2 - h1) - 1;
}
else
{
h3 = h2 - h1;
}
m1 = 60 - m1;
if (m1 + m2 >= 60)
{
m3 = 60 - (m1 + m2);
} else if (m3 < 0)
{
m3 = m3 * -1;
}
else
{
m3 = m1 + m2;
}
System.out.println("duration:" + h3 + "h" + m3 + "min");
If you have a function that returns the number of days since some start date (e.g. dayssince1900) you can just convert both dates to seconds since that start date, do the ABS(d1-d2) then convert the seconds back to whatever format you want e.g. HHHH:MM:SS
Simple e.g.
SecondsSince1900(d)
{
return dayssince1900(d)*86400
+hours(d)*3600
+minutes(d)*60
+seconds(d);
}
diff = ABS(SecondsSince1900(d1)-SecondsSince1900(d2))
return format(diff DIV 3600)+':'+format((diff DIV 60) MOD 60)+':'+format(diff MOD 60);
Hum: Not that simple if you have to take into account the leap seconds astronomers are keen to put in from time to time.

Non-linear counter

So I have a counter. It is supposed to calculate the current amount of something. To calculate this, I know the start date, and start amount, and the amount to increment the counter by each second. Easy peasy. The tricky part is that the growth is not quite linear. Every day, the increment amount increases by a set amount. I need to recreate this algorithmically - basically figure out the exact value at the current date based on the starting value, the amount incremented over time, and the amount the increment has increased over time.
My target language is Javascript, but pseudocode is fine too.
Based on AB's solution:
var now = new Date();
var startDate1 = new Date("January 1 2010");
var days1 = (now - startDate1) / 1000 / 60 / 60 / 24;
var startNumber1 = 9344747520;
var startIncrement1 = 463;
var dailyIncrementAdjustment1 = .506;
var currentIncrement = startIncrement1 + (dailyIncrementAdjustment1 * days1);
startNumber1 = startNumber1 + (days1 / 2) * (2 * startIncrement1 + (days1 - 1) * dailyIncrementAdjustment1);
Does that look reasonable to you guys?
It's a quadratic function. If t is the time passed, then it's the usual at2+bt+c, and you can figure out a,b,c by substituting the results for the first 3 seconds.
Or: use the formula for the arithmetic progression sum, where a1 is the initial increment, and d is the "set amount" you refer to. Just don't forget to add your "start amount" to what the formula gives you.
If x0 is the initial amount, d is the initial increment, and e is the "set amount" to increase the incerement, it comes to
x0 + (t/2)*(2d + (t-1)*e)
If I understand your question correctly, you have an initial value x_0, an initial increment per second of d_0 and an increment adjustment of e per day. That is, on day one the increment per second is d_0, on day two the increment per second is d_0 + e, etc.
Then, we note that the increment per second at time t is
d(t) = d_0 + floor(t / S) * e
where S is the number of seconds per day and t is the number of seconds that have elapsed since t = t_0. Then
x = x_0 + sum_{k < floor(t / S)} S * d(k) + S * (t / S - floor(t / S)) * d(t)
is the formula that you are seeking. From here, you can simplify this to
x = x_0 + S * floor(t / S) d_0 + S * e * (floor(t / S) - 1) * floor(t / S) / 2.
use strict; use warnings;
my $start = 0;
my $stop = 100;
my $current = $start;
for my $day ( 1 .. 100 ) {
$current += ($day / 10);
last unless $current < $stop;
printf "Day: %d\tLeft %.2f\n", $day, (1 - $current/$stop);
}
Output:
Day: 1 Left 1.00
Day: 2 Left 1.00
Day: 3 Left 0.99
Day: 4 Left 0.99
Day: 5 Left 0.98
...
Day: 42 Left 0.10
Day: 43 Left 0.05
Day: 44 Left 0.01

Resources