Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Incorrect result when using EXSLT date:seconds() function in xslt code

Status
Not open for further replies.

eguthrie

Programmer
Nov 30, 2001
51
US
I'm using the date:seconds function (from the EXSLT date and time functions) to obtain the number of seconds in a duration string, but I'm getting incorrect results.

For example, for the following xslt code, I would expect the result to be 85904. Instead, I'm getting a result 1000 times greater: 85904000.
<xsl:value-of select="date:seconds('PT23H51M44S')"/>

I'm using Xslt version 1.0. Here is what is at the top of my file --
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:date="
Can anyone help?
 
EGuthrie,

Can you show us a self-contained XML + XSLT combination that reproduces your problem? And name the XSLT processor you're using?

Just tried with Saxon and .NET processors and everything is working as it should.
 
Hi atlopes,
I looked further and found that we are using the Javascript implementation of these functions provided by Chris Bays 2001-06-12 --
/**
<doc:module date="2001-06-12">
<doc:module>exslt:date-time</doc:module>
<doc:name>dates</doc:name>
<doc:version>2.0</doc:version>
<doc:language>exslt:javascript</doc:language>
<doc:meta>
<doc:author email="chris@bayes.co.uk" url=" Bayes</doc:author>
<doc:summary>Implementation of EXSLT - Dates ( <doc:todo>_validDuration is not 100%</doc:todo>
<doc:todo>All timezone code.</doc:todo>
</doc:meta>
</doc:module>
**/

Here is the function. The part in red below is returning the incorrect value. If I change it to "return oDate.Seconds()/1000", I obtain the desired result--
function seconds(){//
if (arguments.length > 0){
var oDate;
if ((oDate = _validDate(arguments[0], "xs:dateTime")) ||
(oDate = _validDate(arguments[0], "xs:date")) ||
(oDate = _validDate(arguments[0], "xs:gYearMonth")) ||
(oDate = _validDate(arguments[0], "xs:gYear"))
)
return oDate.valueOf()/1000;
else
if (oDate = _validDuration(arguments[0]))
return oDate.Seconds();
else
return Number.NaN;
}else
return Math.floor(new Date().valueOf()/1000);//current local date/time
}

I don't understand enough about his code to determine why it isn't returning the value from the first "if" section, rather than from the "else if" section.
But in any case, shouldn't the result in the "else if" section be divided by 1000?
 
eguthrie said:
I don't understand enough about his code to determine why it isn't returning the value from the first "if" section, rather than from the "else if" section.
But in any case, shouldn't the result in the "else if" section be divided by 1000?
Hi eguthrie,
first of all the next time when you post your code then place it please between the [pre]
Code:
[/pre] and [pre]
[/pre] tags.
Then it will be better readable for us.
If you don't understand why your code isn't returning A but B then use for example console.log() to print out the computed values for debugging purposes.
By the way, you use in your [tt]if[/tt]-conditions the assignment operator [tt]=[/tt] instead of the comparition operator ==

 
Hi eguthrie,
OK, but when the JavaScript module is from 2001, then nowaday it's pretty old.
Probably something essential could have changed since there: an another module which is called or a library, which in the year 2001 was originally returning time seconds, but now it returns rather time in milliseconds.
I would not be annoyed with that and just simply divide the result by 1000 and let it go.
 
EGuthrie,

It's an implementation problem. The function Seconds() of the Duration object is returning milliseconds.

JavaScript:
this.Seconds = function(){if (this.years || this.months)return Number.NaN;return this.days*giDayMill + this.hours*giHourMill + this.minutes*giMinMill + this.seconds*giSecMill;}

where each of gi*Mill variables holds the number in milliseconds for each point in the time scale (days, hours, minutes, and seconds). There is nothing you can do unless change the behavior.

As to the other two questions: the function is returning the value from the "else if" because the first condition returns false for invalid dates (as is the case of duration strings); and @mikrom, the condition is being tested on the result of the assignment, that is, on what oDate holds after the assignment, so it's ok to use = instead of == in this case (it reads as if it were written as [tt](oDate = _validDate(arguments[0], "xs:dateTime")) == true[/tt]).
 
Hi atlopes,
ok, but according to your investigations the conclusion is to divide the result by 1000.
 
I think the function in the file date.msxsl.xsl would need to be adjusted, because it isn't consistent in what it returns. It can return either seconds or milliseconds. So I can't simply divide the function result by 1000.

function seconds(){//
if (arguments.length > 0){
var oDate;
if ((oDate = _validDate(arguments[0], "xs:dateTime")) ||
(oDate = _validDate(arguments[0], "xs:date")) ||
(oDate = _validDate(arguments[0], "xs:gYearMonth")) ||
(oDate = _validDate(arguments[0], "xs:gYear"))
)
return oDate.valueOf()/1000; -->Correct (seconds)
else
if (oDate = _validDuration(arguments[0]))
return oDate.Seconds(); -->**Wrong** (milliseconds)
else
return Number.NaN;
}else
return Math.floor(new Date().valueOf()/1000); -->Correct (seconds) //current local date/time
}
 
Yes, you have to change the behavior of the library at the point I mentioned, the function Seconds of the Duration object. Basically, change it to
JavaScript:
this.Seconds = function(){
  if (this.years || this.months)
    return Number.NaN;
  return (this.days*giDayMill + this.hours*giHourMill + this.minutes*giMinMill + this.seconds*giSecMill) / 1000;
}
 
atlopes,
If I simply modify date.msxsl.xsl to change the faulty statement within function seconds() from
return oDate.Seconds() to return oDate.Seconds()/1000 , that corrects the result.

Is that not the adjustment I should make?




 
EGuthrie,

Your choice, really - forget about my "you have to", it should have been "you may".

I think that the effect in the library will be the same since Duration.Seconds() is called only once, precisely at the point you intend to correct from milliseconds to seconds. It's your choice to correct it at the origin (a function named Seconds() shouldn't return seconds, instead of milliseconds?), or at where the function is called.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top