Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Option to return DateTime properties as ISO strings #1090

zirkelc started this conversation in Ideas
Discussion options

I would like to submit a proposal to convert Neo4 Date and Time object into ISO strings when returning these values from the driver.


The driver returns properties and values, which are defined in Neo4j as DateTime, Date or Time, in their native Java format. That means, the ISO string 1970年01月01日T00:00:00.000Z

return datetime('1970-01-01T00:00:00.000Z') as datetime

will be returned as Neo4j DateTime object and serialised into JSON as

{
 "datetime": {
 "year": 1970,
 "month": 1,
 "day": 1,
 "hour": 0,
 "minute": 0,
 "second": 0,
 "nanosecond": 0,
 "timeZoneOffsetSeconds": 0
 }
}

However, this format is not very useful when working with JavaScript. I know there are methods like DateTime.toStandardDate() to get a plain JS Date, but there are still some drawbacks:

  1. the Neo4j database connection is usually abstracted or hidden by a backend layer, that means downstream services receive the serialised JSON format instead of the Neo4j DateTime object that provide the conversion functions toStandardDate().

  2. other services that receive the data as JSON have to install the neo4j driver package to create a Neo4j DateTime object via its constructor and then convert it to a JS Date. Or they have to implement their own function to create a JS Date from this format.

  3. the conversion from Neo4j DateTime to JS Date looses timezone information, because JS Date is not timezone aware and always converts dates into local time. The conversion of 1970年01月01日T00:00:00.000Z from Neo4j DateTime to JS Date and back to Neo4j DateTime alters the original ISO string and adds a timezone offset of 3600 seconds. Of course, it is still the original date and time, but the timezone information was changed. That is the reason we usually avoid working with the native JS Date and instead use libraries like Luxon, Moment, or Day.js that retain the original timezone.

image

These drawbacks could be solved if the driver would be able to convert the DateTime, Date and Time objects as ISO strings instead of the corresponding objects. For example, as an option disableTemporalTypes like the conversion of Neo4j Integers to native JS numbers:

var driver = neo4j.driver(
 'neo4j://localhost',
 neo4j.auth.basic('neo4j', 'password'),
 { 
 disableLosslessIntegers: true, 
 disableTemporalTypes: true // => convert datetime to ISO
 }
)

Or it could be implemented as mappedResultTransformer for the new Driver.executeQuery() with a conversion function for each native Java type:

const result = await driver.executeQuery("query", params, {
 resultTransformer: neo4j.resultTransformer.mappedResultTransformer({
 map: (record) => record.toObject({ 
 converter: {
 dateTime: (value: DateTime) => value.toString() // convert datetime to ISO
 }),
 collect: records => records
 })
})

Conversion of DateTime, Date and Time to ISO strings would also help, because JavaScript Date doesn't support date-only 1970年01月01日 and time-only 00:00:00.000Z. In this cases, the conversion to JS Date potentially alters real information.

You must be logged in to vote

Replies: 1 comment 9 replies

Comment options

This type of boiler plate is something we'd like to handle for making the driver easier to integrate to javascript environments.

One alternative is work with hydration/dehydration hooks can transform driver objects to domain or some library shape.

Some usage example:

const driver = neo4j.driver(URL, CREDENTIALS, {
 hydrationHooks: {
 LocalDateTime: (value: LocalDateTime) => value.toString() // convert to datetime string,
 DateTime: (value: DateTime) => fromNeo4jDateTimeToMyFancyLibraryDateTime(value) // converts to the fancy library date time 
 },
 dehydrationHooks: {
 DateTime: {
 isDateTime: checkIfValueIsFromMyFancyLibraryDateTime, // check if object is from the temporal library you are using
 convert: fromMyFancyLibraryDateTimeToNeo4jDateTime // converts to neo4j date time
 }
 }
})
You must be logged in to vote
9 replies
Comment options

bigmontz Nov 6, 2023
Collaborator

Hey @zirkelc. I started to do POC on hydration and we have some PR with simple code usage example.

The code has the happy path working. If you want, you can download the driver and test it locally.

Feedbacks are more than welcome.

#1157

Comment options

Hey @bigmontz thanks for pinging me! I tested it locally and it looks very promising! I have two remarks:

  • I added a console log isTypeInstance() and noticed it is being called for lots of other values unrelated to the actual query, for example for the username, password, ip address, cypher query string etc. Is this on purpose?
  • the name isTypeInstance could be misleading if someone is working with primitives like strings instead of objects. For example, I working with plain ISO date strings instead of Date instances.

I think this feature is a huge benefit for the library! Another things that comes to my mind, maybe something for the docs, is to conditionally hydrate Integer into JavaScript numbers or BigInts.

hydrationHooks: {
	Integer(integer) {
		console.log('hydrate', { integer })
		return integer.inSafeRange()
			? integer.toInt()
			: integer.toBigInt();
	}
}
Comment options

bigmontz Nov 7, 2023
Collaborator

Thanks for the quick feedback.

About the integer hydration, It is in the code right now but I will remove since it could cause issues in the driver behaviour. This hydrations are being done in the lower level of the driver, in the packstream level (protocol to serialize and deserialize structures and data) and if the user replace Integer for stuff which are not number, Integer and BigInt, the driver might start to behaving quite strange.

About the isTypeInstance, I think I've let it too open for the POC and I might block to only be called in the query parameters to avoid strange and dangerous user of the driver.

Comment options

Hi @bigmontz

is there a plan if/when these hydration hooks will land in the official driver?

Comment options

bigmontz Jun 4, 2024
Collaborator

Sorry for the late reply. We have plans for it, the feature is our backlog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Ideas
Labels
None yet
2 participants

AltStyle によって変換されたページ (->オリジナル) /