Skip to content

Commit

Permalink
Add Neo4j temporal types
Browse files Browse the repository at this point in the history
  • Loading branch information
johannessen committed Oct 22, 2023
1 parent e671fa5 commit cff7afd
Show file tree
Hide file tree
Showing 10 changed files with 467 additions and 7 deletions.
3 changes: 2 additions & 1 deletion Changes
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Revision history for Neo4j::Types

1.06 UNRELEASED
1.07 UNRELEASED

- Define scalar context for list methods to yield number of elements
- Define properties() to behave the same in list context as in scalar context.
Expand All @@ -9,6 +9,7 @@ Revision history for Neo4j::Types
- Recommend that users don't inherit type implementations from these roles.
- Add Neo4j::Types::Generic namespace for generic type implementations.
- Move spatial point implementation into Neo4j::Types::Generic namespace.
- Add DateTime and Duration temporal types.

1.00 2021-01-18

Expand Down
2 changes: 1 addition & 1 deletion dist.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ license = Artistic_2_0
copyright_holder = Arne Johannessen
copyright_year = 2021-2023

version = 1.06
version = 1.07
release_status = unstable

[@Author::AJNN]
Expand Down
29 changes: 29 additions & 0 deletions lib/Neo4j/Types/DateTime.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use strict;
use warnings;

package Neo4j::Types::DateTime;
# ABSTRACT: Represents a Neo4j temporal instant value


sub epoch {
my ($self) = @_;

return ($self->days // 0) * 86400 + ($self->seconds // 0);
}


sub type {
my ($self) = @_;

return 'DATE' unless defined $self->seconds;

unless (defined $self->days) {
return 'LOCAL TIME' unless defined $self->tz_offset;
return 'ZONED TIME';
}

return 'LOCAL DATETIME' unless defined $self->tz_offset || defined $self->tz_name;
return 'ZONED DATETIME';
}

1;
159 changes: 159 additions & 0 deletions lib/Neo4j/Types/DateTime.pod
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# PODNAME: Neo4j::Types::DateTime
# ABSTRACT: Represents a Neo4j temporal instant value

=encoding UTF-8

=head1 SYNOPSIS

$days = $dt->days;
$seconds = $dt->seconds;
$nanoseconds = $dt->nanoseconds;

$epoch = $days * 86400 + $seconds;
$epoch = $dt->epoch;
$epoch_hires = $epoch + $nanoseconds / 1e9;

$tz_name = $dt->tz_name; # like Europe/Paris
$seconds = $dt->tz_offset; # like 3600

$neo4j_type = $dt->type; # like ZONED DATETIME

=head1 DESCRIPTION

Represents a temporal instant value in Neo4j. Potentially includes
date, time, and timezone components.

Neo4j offers the following temporal instant types:

=over

=item * C<DATE>

=item * C<LOCAL TIME> E<8211> no time zone information

=item * C<ZONED TIME> E<8211> has a time zone offset in seconds

=item * C<LOCAL DATETIME> E<8211> no time zone information

=item * C<ZONED DATETIME> E<8211> has a time zone offset in seconds,
or a time zone name from the IANA Olson database

=back

This role is designed to closely match the semantics of the
Neo4j temporal types. For actually working with dates and times
in Perl, the modules recommended by L<Task::Kensho::Dates> are
better suited in most cases. The conversion is easiest using
the Epoch value:

$dt = Neo4j::Types::Generic::DateTime->new( ... );
$epoch_hires = $dt->epoch + $dt->nanoseconds / 1e9;

$datetime = DateTime->from_epoch( epoch => $epoch_hires );
$moment = Time::Moment->from_epoch( $epoch_hires );
$piece = Time::Piece->new( $dt->epoch );

DateTime values may be returned from a Neo4j database server.
Generic DateTime values may also be created locally.
See L<Neo4j::Types::Generic/"DateTime">.

Supported in Neo4j S<version 3.4> and above.

=head1 METHODS

L<Neo4j::Types::DateTime> specifies the following methods.

=head2 days

$days = $dt->days;

Return the number of full days since the Unix epoch.
For C<* TIME> values, return C<undef>.

For the day identified by C<$days>, the
L<Julian Date|https://en.wikipedia.org/wiki/Julian_date>
is exactly C<$days + 2440587.5>.

=head2 epoch

$seconds = $dt->epoch;

Return the full seconds since the Unix epoch, ignoring
leap seconds. Values of the type C<TIME> are interpreted
as referring to S<1 January 1970>.

=head2 nanoseconds

$nanoseconds = $dt->nanoseconds;

Return the nanoseconds since the start of the second identified
by C<seconds()>. For C<DATE> values, return C<undef>.

=begin comment

=head2 new

$dt = Neo4j::Types::DateTime->new( ... );

Constructs a new generic Neo4j temporal instant value.
See L<Neo4j::Types::Generic/"DateTime">.

=end comment

=head2 seconds

$seconds = $dt->seconds;

Return the seconds since the start of the day.
For C<DATE> values, return C<undef>.

=head2 type

$neo4j_type = $dt->type;

Return the Neo4j type name for this value as a string.
One of C<DATE>, C<LOCAL TIME>, C<ZONED TIME>,
C<LOCAL DATETIME>, C<ZONED DATETIME>.

=head2 tz_name

$tz_name = $dt->tz_name;

Return the name of the time zone to be used for display purposes.
The name refers to the IANA Olson time zone database.
For example, the time zone name for California would be
C<America/Los_Angeles>.
For C<DATE> values and C<LOCAL *> values, return C<undef>.

For a display time zone defined by standard offset only, this
method will return a zone name in the C<Etc> area. Note that
such zone names follow the POSIX sign convention, which uses
a positive sign west of Greenwich. This is the inverse of the
S<ISO convention> usually used for time zone offsets.

=head2 tz_offset

$seconds = $dt->tz_offset;

Return the number of seconds to be added to the time for display
purposes. A positive sign is used east of Greenwich.
For example, for standard time in California, the offset
from UTC would be -28800 seconds.
For C<DATE> values and C<LOCAL *> values, return C<undef>.

To define a display time zone, it is sufficient for either the
time zone name or a numerical time offset to be available.
If this method returns C<undef>, you need to use C<tz_name()>
instead.

=head1 SEE ALSO

=over

=item * L<Neo4j::Types::Generic/"DateTime">

=item * L<Neo4j::Types::ImplementorNotes/"TEMPORAL TYPES">

=item * L<"Temporal values" in Neo4j Cypher Manual|https://neo4j.com/docs/cypher-manual/5/values-and-types/temporal/>

=back
8 changes: 8 additions & 0 deletions lib/Neo4j/Types/Duration.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use strict;
use warnings;

package Neo4j::Types::Duration;
# ABSTRACT: Represents a Neo4j temporal duration value


1;
65 changes: 65 additions & 0 deletions lib/Neo4j/Types/Duration.pod
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# PODNAME: Neo4j::Types::Duration
# ABSTRACT: Represents a Neo4j temporal duration value

=encoding UTF-8

=head1 SYNOPSIS

$months = $duration->months;
$days = $duration->days;
$seconds = $duration->seconds;
$nanoseconds = $duration->nanoseconds;

=head1 DESCRIPTION

Represents a temporal duration value in Neo4j.
Includes month, days, seconds, and nanoseconds components,
which are all expressed as integer numbers.
The length of the duration is defined by the combination
of these four components.

Duration values may be returned from a Neo4j database server.
Generic Duration values may also be created locally.
See L<Neo4j::Types::Generic/"Duration">.

Supported in Neo4j S<version 3.4> and above.

=head1 METHODS

L<Neo4j::Types::Duration> specifies the following methods.

=head2 days

$days = $duration->days;

Return the size of the "days" component of this duration.

=head2 months

$months = $duration->months;

Return the size of the "months" component of this duration.

=head2 nanoseconds

$nanoseconds = $duration->nanoseconds;

Return the size of the "nanoseconds" component of this duration.

=head2 seconds

$seconds = $duration->seconds;

Return the size of the "seconds" component of this duration.

=head1 SEE ALSO

=over

=item * L<Neo4j::Types::Generic/"Duration">

=item * L<Neo4j::Types::ImplementorNotes/"TEMPORAL TYPES">

=item * L<"Temporal values" in Neo4j Cypher Manual|https://neo4j.com/docs/cypher-manual/5/values-and-types/temporal/>

=back
54 changes: 54 additions & 0 deletions lib/Neo4j/Types/Generic.pod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,56 @@ be better optimised for use with the respective driver.
As long as each of them performs the appropriate role
from L<Neo4j::Types>, they should all be interchangeable.

=head1 DateTime

Neo4j::Types::Generic::DateTime offers the following methods
in addition to those defined in L<Neo4j::Types::DateTime>.

=head2 new

$dt = Neo4j::Types::Generic::DateTime->new({
days => $days,
seconds => $seconds,
nanoseconds => $nanoseconds,
tz_offset => $offset_seconds,
tz_name => $iana_tz_name,
});
$dt = Neo4j::Types::Generic::DateTime->new( $epoch );
$dt = Neo4j::Types::Generic::DateTime->new( $epoch, $tz );

Create a new generic temporal instant value.
For the description of the parameters, see
L<Neo4j::Types::DateTime/"METHODS">.
The type of the value will be intrinsically defined by the
parameters you provide.

Instead of giving the parameters hash ref, you can alternatively
give the Unix epoch with or without time zone identification.
This will always create a C<LOCAL DATETIME> or C<ZONED DATETIME>
value, as appropriate.
If C<$tz> begins with a letter, it will be treated as an IANA
Olson time zone database entry name; if it begins with a digit
or a sign, it will be treated as an offset in seconds.

=head1 Duration

Neo4j::Types::Generic::Duration offers the following methods
in addition to those defined in L<Neo4j::Types::Duration>.

=head2 new

$dt = Neo4j::Types::Generic::Duration->new({
months => $months,
days => $days,
seconds => $seconds,
nanoseconds => $nanoseconds,
});

Create a new generic temporal duration value.
For the description of the parameters, see
L<Neo4j::Types::Duration/"METHODS">.
Missing parameters will be assumed to have the value C<0>.

=head1 Point

Neo4j::Types::Generic::Point offers the following methods
Expand Down Expand Up @@ -79,6 +129,10 @@ dimensions, this method returns C<undef>.

=item * L<Neo4j::Types>

=item * L<Neo4j::Types::DateTime>

=item * L<Neo4j::Types::Duration>

=item * L<Neo4j::Types::Point>

=item * L<Neo4j::Types::ImplementorNotes>
Expand Down

0 comments on commit cff7afd

Please sign in to comment.