-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
ZonedDateTimeIndexKey.java
136 lines (123 loc) · 4.61 KB
/
ZonedDateTimeIndexKey.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* Copyright (c) 2002-2018 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.impl.index.schema;
import java.time.ZoneId;
import java.time.ZoneOffset;
import org.neo4j.values.storable.DateTimeValue;
import org.neo4j.values.storable.TimeZones;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.ValueGroup;
import org.neo4j.values.storable.Values;
import static java.lang.String.format;
/**
* Includes value and entity id (to be able to handle non-unique values). A value can be any {@link DateTimeValue}.
* <p>
* With these keys the DateTimeValues are sorted
* 1. by epochSecond
* 2. by nanos
* 3. by effective Offset west-to-east
* 4. non-named TimeZones before named TimeZones. Named Timezones alphabetically.
*/
class ZonedDateTimeIndexKey extends NativeIndexSingleValueKey<ZonedDateTimeIndexKey>
{
static final int SIZE =
Long.BYTES + /* epochSecond */
Integer.BYTES + /* nanoOfSecond */
Integer.BYTES + /* timeZone */
ENTITY_ID_SIZE; /* entityId */
long epochSecondUTC;
int nanoOfSecond;
short zoneId;
int zoneOffsetSeconds;
@Override
public Value asValue()
{
return TimeZones.validZoneId( zoneId ) ?
DateTimeValue.datetime( epochSecondUTC, nanoOfSecond, ZoneId.of( TimeZones.map( zoneId ) ) ) :
DateTimeValue.datetime( epochSecondUTC, nanoOfSecond, ZoneOffset.ofTotalSeconds( zoneOffsetSeconds ) );
}
@Override
public void initValueAsLowest( ValueGroup... valueGroups )
{
epochSecondUTC = Long.MIN_VALUE;
nanoOfSecond = Integer.MIN_VALUE;
zoneId = Short.MIN_VALUE;
zoneOffsetSeconds = Integer.MIN_VALUE;
}
@Override
public void initValueAsHighest( ValueGroup... valueGroups )
{
epochSecondUTC = Long.MAX_VALUE;
nanoOfSecond = Integer.MAX_VALUE;
zoneId = Short.MAX_VALUE;
zoneOffsetSeconds = Integer.MAX_VALUE;
}
@Override
public int compareValueTo( ZonedDateTimeIndexKey other )
{
int compare = Long.compare( epochSecondUTC, other.epochSecondUTC );
if ( compare == 0 )
{
compare = Integer.compare( nanoOfSecond, other.nanoOfSecond );
if ( compare == 0 &&
// We need to check validity upfront without throwing exceptions, because the PageCursor might give garbage bytes
TimeZones.validZoneOffset( zoneOffsetSeconds ) &&
TimeZones.validZoneOffset( other.zoneOffsetSeconds ) )
{
// In the rare case of comparing the same instant in different time zones, we settle for
// mapping to values and comparing using the general values comparator.
compare = Values.COMPARATOR.compare( asValue(), other.asValue() );
}
}
return compare;
}
@Override
public String toString()
{
return format( "value=%s,entityId=%d,epochSecond=%d,nanoOfSecond=%d,zoneId=%d,zoneOffset=%d",
asValue(), getEntityId(), epochSecondUTC, nanoOfSecond, zoneId, zoneOffsetSeconds );
}
@Override
public void writeDateTime( long epochSecondUTC, int nano, int offsetSeconds )
{
this.epochSecondUTC = epochSecondUTC;
this.nanoOfSecond = nano;
this.zoneOffsetSeconds = offsetSeconds;
this.zoneId = -1;
}
@Override
public void writeDateTime( long epochSecondUTC, int nano, String zoneId )
{
this.epochSecondUTC = epochSecondUTC;
this.nanoOfSecond = nano;
this.zoneId = TimeZones.map( zoneId );
this.zoneOffsetSeconds = 0;
}
@Override
protected Value assertCorrectType( Value value )
{
if ( !(value instanceof DateTimeValue) )
{
throw new IllegalArgumentException(
"Key layout does only support DateTimeValue, tried to create key from " + value );
}
return value;
}
}