How to convert ticks into a readable datetime with XSLT? - datetime

I have an XML with timestamps like this:
<node stamp="1236888746689" />
And I would like to display them in the result HTML as date with time.
Is there a way to do it with XSLT (any Version)?
EDIT:
I am using XSLT2.0 with Saxon9. The base date is 1970-01-01 0:00.

You take the date 1970-01-01T00:00:00 and add as many milliseconds as the value of the stamp tells you:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/TR/xhtml1/strict">
<xsl:template match="node">
<xsl:value-of
select='xs:dateTime("1970-01-01T00:00:00") + #stamp * xs:dayTimeDuration("PT0.001S")'/>
</xsl:template>
</xsl:stylesheet>

If you are using an XSLT 1.0 processor which supports the EXSLT date functions (I've just tested this with libxslt in PHP), you can use date:add() and date:duration():
<xsl:value-of select="date:add('1970-01-01T00:00:00Z', date:duration(#stamp div 1000))"/>
The date:duration() function takes a number of seconds (so you have to divide your milliseconds by 1000) and turns it into a "duration" (in this case, "P14315DT20H12M26.6889998912811S"), which is then added to the start of your epoch (looks like the standard epoch, for this stamp) with date:add() to get a stamp of "2009-03-12T20:12:26.6889998912811Z". You can then format this using the EXSLT date functions or just substring(), depending on what you need.

Belated answer, yes, I know, but I couldn't find the one I was looking for here, so I thought I'd pay it forward with my solution.
My XML was a few nodes dumped from Drupal using export_node and drush. I was using the xslt processor in PHP5, which only supports xslt 1.0. Some EXSLT functions appear to be supported, but I couldn't tell whether my syntax was wrong or the function I was trying to use was not supported. Anyway, the following worked for me. I used the example code from w3schools.com, but added a line right after declaring the xsltprocessor, like below:
$xp = new XsltProcessor();
$xp->registerPHPFunctions();
PHP has a trivial function for date conversion, so I cheated and used the PHP processor, since I was already using it to transform my xsl.
<xsl:for-each select="node_export/node">
<xsl:value-of select="php:function('date', 'n-j-y', number(timestamp))"/>
</xsl:for-each>
Hope this helps someone out there. I was banging my head for quite a while as I worked this one out.

If you wanted to use an XSL 1.0 processor that does not support the EXSLT date and time functions this is non-trivial, but it has been done.
You can have a look at Katy Coe's XSLT 1.0 implementation of the "iso-from-unix" function. It's part of a rather huge "free for non-commercial use" set of date and time functions she created.
However, your XSL processor must support the "http://exslt.org/functions" namespace for this implementation to work. Other than that there is no dependency on EXSLT.
P.S.: I'm aware that a Unix timestamp and ticks are not exactly the same thing. They are close enough, though.

XSLT is Turing complete, so there must be a way. :) Knowing at least a bit of XSLT, it will probably involve recursion.
You don't specify the exact interpretation of your "ticks", I'm guessing milliseconds since some epoch, but which? 1970?

Related

jmeter converting a human readable date to Epoch

I have a script that needs two timestamps, one for 'today' at 02:30 and one for 'tomorrow' at 02:30. To generate the dates was fairly easy, using;
date1=${__time("yyyy.MM.dd 02:30:00")}
date2=${__timeShift("yy.MM.dd 02:30:00",,P1D,,)}
But the POST request needs the dates in Epoch format. How can I convert the output of the above into Epochs?
An option that I found was to use;
date1a=date1.getTime().toString()
But that didn't work (no signature of method). Related to that I did find a jmeter 5.3 bug where the dateutil.jar is missing, but adding it made no difference.
There are lots of options for converting Epoch to human readable, but they aren't reversible processes.
Alternatively, is there a way of calculating the Epoch directly, again for 'today' at 2:30 and 'tomorrow' at 2:30?
Don't inline JMeter Functions or Variables into scripts, as per JSR223 Sampler documentation
The JSR223 test elements have a feature (compilation) that can significantly increase performance.
When using this feature, ensure your script code does not use JMeter variables or JMeter function calls directly in script code as caching would only cache first replacement. Instead use script parameters
I believe you can achieve your goal using good old SimpleDateFormat, example code to parse your string and add 24 hours to it:
def today = new java.text.SimpleDateFormat('yyyy.MM.dd hh:mm:ss').parse('2020.11.06 02:30:00')
log.info('Today: ' + today)
def tomorrow = new Date(today.getTime() + 86400000L)
log.info('Tomorrow: ' + tomorrow)
log.info('Today epoch : ' + today.getTime())
log.info('Tomorrow epoch: ' + tomorrow.getTime())
Demo:
More information on Groovy scripting in JMeter: Apache Groovy - Why and How You Should Use It

DateTimeParseException while trying to perform ZonedDateTime.parse

Using Java 8u222, I've been trying a silly operation and it incurs in an error that I'm not being able to fully understand. The line code:
ZonedDateTime.parse("2011-07-03T02:20:46+06:00[Asia/Qostanay]");
The error:
java.time.format.DateTimeParseException: Text '2011-07-03T02:20:46+06:00[Asia/Qostanay]' could not be parsed, unparsed text found at index 25
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1952)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:582)
Using the same date (although the timezone could be incorrect, the intention is just testing here), I changed the square bracket's value and it works, I mean:
ZonedDateTime.parse("2011-07-03T02:20:46+06:00[Europe/Busingen]);
It works as expected, as well as other values such:
ZonedDateTime.parse("2011-07-03T02:20:46+06:00[Asia/Ulan_Bator]")
ZonedDateTime.parse("2011-07-03T02:20:46+06:00[SystemV/CST6CDT]")
I found some similar questions such as the one below, but not precisely the same usage that I'm trying / facing.
Error java.time.format.DateTimeParseException: could not be parsed, unparsed text found at index 10
Does someone have an understanding of Java Date API to help me out to grasp what I'm doing wrong here?
Thanks.
Asia/Qostanay is a zone which doesn't exist in the JDK8's list of timezones. It was added later.
If you don't care about the location of the timezone then just splice the [...] part of the string off the end before parsing. Knowing that the time is +06:00 is going to sufficient for almost all purposes.
Alternatively, upgrade to a more recent version of Java.

Testing DAX calculation with NBi

I'm doing some research on automated test tool for our SSAS Tabular project. I found NBi and thought it is really cool. I attempted to set it up and successfully ran some basic tests. However, when I attempted to test dax calculation, it says "Function not found" (see screenshot). It sounds like it does not support SUM, but given that SUM is a basic function I would imagine it should work. Since I'm new to this tool, I wanted to double check if I've done something wrong or it is simply what the error is saying... (not supported function).
I went back and review NBi documentation and it mentioned to check out their NCAL.dll for all available expression. Unfortunately, I'm unable to open a readable version of that dll file. Any help is appreciated.
Here is the formula I want to test:
=SUMX(FILTER(MyTable, AND(MyTable[Date] = EARLIER(MyTable[Date]), MyTable[Account] = EARLIER(MyTable[Account]))), MyTable[Amount])
XML code (nbits) file
<test name="My second test: Calculated column compared to DAX formula">
<system-under-test>
<execution>
<query connectionString="Provider=MSOLAP.7;Data Source...">
<![CDATA[
EVALUATE
SUMMARIZE (MyTable, MyTable[Date], MyTable[Account], MyTable[Amount], MyTable[CalculatedAmount])
]]>
</query>
</execution>
</system-under-test>
<assert>
<evaluate-rows>
<variable column-index="0">Date</variable>
<variable column-index="1">Account</variable>
<variable column-index="2">Amount</variable>
<variable column-index="3">CalculatedAmount</variable>
<expression column-index="3" type="numeric" tolerance="0.01"> = SUMX(FILTER(MyTable, AND(MyTable[Date] = EARLIER(MyTable[Date]), MyTable[Account] = EARLIER(MyTable[Account]))), MyTable[Amount])</expression>
</evaluate-rows>
</assert>
</test>
NBi supports the evaluation of DAX queries in the query tag but not in an expression tag. Expression and evaluate-rows tags are not designed to compare two queries. To achieve this, change your test to use the assertion equalTo between your two queries. It will be easier and will work.
I guess a better question would be how do I test a measure and a
calculated column in term of ensuring that another developer doesn't
accidentally change the calculation/expression I entered when
designing the Tabular model?
I'll answer at three levels: conceptual, logical and technical.
At the conceptual level, your test is wrong: you should never use the same implementation in your assertion and in your system-under-test. This is not specifc to NBi or to any framework but to all automated tests. The role of a test is not ensure that someone doesn't change something but to ensure that something gives the correct result. Comparing an artifact to itself will always result in a green test even if your implementation is wrong. In this case, you must change your assertion with a concrete static result or you need to create a sql statements resulting in the same calculation of your database or find another query in MDX resulting in the same result.
At the logical level the following sentence is not correct
Here is the formula I want to test:
You've defined this formula in your assert and not in your system-under-test. It means that it's not what you're testing but it's your reference (something you're 100% sure that it's correct). What you're testing is the query EVALUATE SUMMARIZE (MyTable, MyTable[Date], MyTable[Account], MyTable[Amount], MyTable[CalculatedAmount]).
At the technical level, using an evaluate-rows is nopt the correct option. This assertion is not expecting a function or a query but an expression based on row's variable (no DAX, no SQL, ...). The usage of EARLIER is a clear sign that it won't be possible. In your case, you must compare two queries probably something as:
<assert>
<equalTo>
<column index="0" role="key" type="dateTime"/>
<column index="1" role="key" type="numeric"/>
<column index="2" role="value" type="numeric"/>
<column index="3" role="value" type="numeric" tolerance="0.01"/>
<query>
EVALUATE SUMMARIZE (MyTable, MyTable[Date], MyTable[Account], MyTable[Amount], SUMX(FILTER(MyTable, AND(MyTable[Date] = EARLIER(MyTable[Date]), MyTable[Account] = EARLIER(MyTable[Account]))), MyTable[Amount])
</query>
</equalTo>
</assert>
PS: I'm clearly not a specilist of DAX and I'm not sure the query above is valid from a syntax point of view.

XSL, comparing dates to exclude any past events

I have an RSS of an events feed. I would like to hide previous events.
Assuming XML data subset of
<Navigation Name="ItemList" Type="Children">
<Page ID="x32444" URL="..." Title="Class..."
EventStartDate="20090831T23:00:00" EventEndDate="20090904T23:00:00"
EventStartTime="20090830T15:30:00" EventEndTime="20090830T18:30:00" Changed="20090830T20:28:31" CategoryIds="" Schema="Event"
Name="Class of 2010 BAKE SALE"/>
<Page ID="x32443" URL="x32443.xml?Preview=true&Site=&UserAgent=&IncludeAllPages=true&tfrm=4" Title="Class of 2010 BAKE SALE"
Abstract="Treat yourself with our famous 10-star FRIED ICE CREAM!" EventStartDate="20090831T23:00:00" EventEndDate="20090904T23:00:00"
EventStartTime="20090830T15:30:00" EventEndTime="20090830T18:30:00" Changed="20090830T20:25:35" CategoryIds="" Schema="Event"
Name="Class of 2010 BAKE SALE"/>
<Page ID="x32426" URL="x32426.xml?Preview=true&Site=&UserAgent=&IncludeAllPages=true&tfrm=4" Title="Tribute to ..."
Abstract="Event to recognize and celebrate the lifetime of leadership and service ..."
EventStartDate="20091206T00:00:00" EventEndDate="20091206T00:00:00" EventStartTime="20090828T23:00:00" EventEndTime="20090828T04:00:00"
Changed="20090828T22:09:54" CategoryIds="" Schema="Event" Name="Tribute to ...."/>
</Navigation>
How would I not include anything past today's date
<xsl:apply-template select="Page[#EventStartDate=notBeforeToday()]"/>
Easiest with XSL parameters that you set from outside.
<xsl:param name="today" select="'undefined'" />
<!-- time passes... -->
<xsl:apply-templates select="Page[#EventStartDate < $today]"/>
Your date format is such that you can compare it using string comparison, unless there are different timezones involved. You would simply set
20091001T00:00:00
as the param value for $today. Have a look into your XSLT processor's documentation to see how.
The alternative would be to use an extension function. Here it depends on which extension functions your XSLT processor supports, so this approach won't be portable.
For this purpose, i usually add an extra date attribute in the XML which contains the day number since year 1900.
for example #dateid='9876543' or #seconds="9876675446545"
then i can can easily compare with today or another variable in the XSL.
You can also use this technique to compare times using "Unix time" for example

How can you print an Ada.Calendar.Time variable in Ada?

Need to know how to print a Time variable in Ada. I assume there is no portable way because Time is implementation defined. I've already seen the GNAT.Calendar.Formatting package available under GNAT, I'd also be interested in a GHS for VME.
See package "Ada.Calendar.Formatting" function "Image" for Ada2005. If you have an Ada95 compiler you could and this package isn't available, try my implementation from here
This was written using GNAT 3.15p, so pretty old.
Sure, time output can be portable, Ada.Calendar contains standard functions that extract the components of a time value, so it's straightforward to put together your own conversion package.
For example, here's one. One just needs to either create a minor addition to create a "Formatted_Time" record for a given Time value (see the package's Get_Time() function for guidance), or make Main_Formatter() visible in the package spec.
Generally what I do is use Calendar.Split and then do a 'image on the parts I care about.
Here's an example that displays the date and time using the GNAT.Calendar.Time_IO package:
with ada.calendar;
with gnat.calendar.time_io;
procedure display_time is
begin
gnat.calendar.time_io.put_time(ada.calendar.clock, "Date: %Y/%m/%d Time: %H:%M:%S");
end display_time;
Date/time format options are available here:
https://en.wikibooks.org/wiki/Ada_Programming/Libraries/GNAT.Calendar.Time_IO

Resources