isNumeric = (s) ->
Good source for xsd data types: http://books.xmlschemata.org/relaxng/relax-CHP-19.html
TODO issue #63: add coerce flag to toNative to trigger best-effort coercion
isNumeric = (s) ->
return not isNaN(parseFloat(s)) && isFinite(s)
createDateAsUTC = (date) ->
return new Date(
Date.UTC
date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()
)
convertDateToUTC = (date) ->
return new Date(
date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()
)
(exports ? this).toNative = (value, literalType, isNum, raw) ->
literalType ?= ""
Convert numeric values in a boolean context into their truth values
if literalType is 'xsd:boolean' and isNumeric(value)
if parseFloat(value) is 0
return false
else
return true
These are the numeric (and logical) types which can be converted using JSON.parse (not eval for safety reasons)
if isNum or literalType.match ///
^
xsd\:(
boolean
|byte
|decimal
|double
|float
|int
|integer
|long
|negativeInteger
|nonNegativeInteger
|nonPositiveInteger
|positiveInteger
|short
|unsignedByte
|unsignedInt
|unsignedLong
|unsignedShort
)
$///
TODO is there a distinction between int and integer (can Javascript handle integer or long?)
value = value.replace(/^\+/,'') # suppress redundant plus signs eg: +88
if value.match(/^INF$/)
return 1e9000 # Infinity
if value.match(/^-INF$/)
return -1e9000 # -Infinity
if value.match(/^NaN$/)
return Math.sqrt(-1) # TODO see Number.NaN for better support
return JSON.parse(value)
These are the types which have string values returned, so no transformation is required.
if literalType.match ///
^
xsd\:(
anyURI
|anySimpleType
|base64Binary
|hexBinary
|language
|normalizedString
|notation
|string
|token
|ENTITY
|ENTITIES
|ID
|IDREF
|IDREFS
|Name
|NCName
|NMTOKEN
|NMTOKENS
|QName
)
$///
TODO should normalizedString,NMTOKEN,Name,NCName,hexBinary raise errors or coerce if the value is invalid?
return value
if not literalType
if not value?
return raw
These are the types which have date and time values which have javascript native equivalents
if literalType.match ///
^
xsd\:(
date
|dateTime
)
$///
http://stackoverflow.com/a/20463521/1234699 Great writeup on JS date details http://stackoverflow.com/a/14006555/1234699 createDateAsUTC and convertDateToUTC
r = new Date(value) # TODO harder trying is needed: no TZ? negative years?
r = createDateAsUTC(r)
offsetMin = r.getTimezoneOffset()
console.log “offsetMin:”, offsetMin
if literalType is 'xsd:date' and offsetMin
r.setHours(0)
r.setMinutes(offsetMin)
r = convertDateToUTC(r)
r.setTimezone(“UTC”) r.setSeconds(0)
if offsetMin and false
console.log "before:",r
console.log r.toLocaleString(“en-US”, {timeZone: ‘UTC’})
console.log "after:",r
console.log “RRRRRRRR”,r
return r
These are the Data types which would require special libraries to express in JS
if literalType.match ///
^
xsd\:(
duration
|gDay
|gMonth
|gMonthDay
|gYear
|gYearMonth
|time
)
$///
return value
return # otherwise return undefined to signal abandonment