a40dc01095159ef99ecb8146b552c6b1d82f9783
[vxquery.git] / vxquery-core / src / main / java / org / apache / vxquery / datamodel / accessors / atomic / XSDateTimePointable.java
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.vxquery.datamodel.accessors.atomic;
18
19 import java.util.Calendar;
20 import java.util.TimeZone;
21
22 import org.apache.vxquery.datamodel.api.IDate;
23 import org.apache.vxquery.datamodel.api.ITime;
24 import org.apache.vxquery.datamodel.api.ITimezone;
25 import org.apache.vxquery.datamodel.util.DateTime;
26
27 import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
28 import edu.uci.ics.hyracks.data.std.api.AbstractPointable;
29 import edu.uci.ics.hyracks.data.std.api.IPointable;
30 import edu.uci.ics.hyracks.data.std.api.IPointableFactory;
31 import edu.uci.ics.hyracks.data.std.primitive.BytePointable;
32 import edu.uci.ics.hyracks.data.std.primitive.IntegerPointable;
33 import edu.uci.ics.hyracks.data.std.primitive.ShortPointable;
34
35 /**
36  * The datetime is split up into eight sections. Due to leap year, we have decided to keep the
37  * storage simple by saving each datetime section separately. For calculations you can access
38  * YearMonth (months) and DayTime (milliseconds) values.
39  * 
40  * @author prestoncarman
41  */
42 public class XSDateTimePointable extends AbstractPointable implements IDate, ITime, ITimezone {
43     public final static int YEAR_OFFSET = 0;
44     public final static int MONTH_OFFSET = 2;
45     public final static int DAY_OFFSET = 3;
46     public final static int HOUR_OFFSET = 4;
47     public final static int MINUTE_OFFSET = 5;
48     public final static int MILLISECOND_OFFSET = 6;
49     public final static int TIMEZONE_HOUR_OFFSET = 10;
50     public final static int TIMEZONE_MINUTE_OFFSET = 11;
51
52     public static final ITypeTraits TYPE_TRAITS = new ITypeTraits() {
53         private static final long serialVersionUID = 1L;
54
55         @Override
56         public boolean isFixedLength() {
57             return true;
58         }
59
60         @Override
61         public int getFixedLength() {
62             return 12;
63         }
64     };
65
66     public static final IPointableFactory FACTORY = new IPointableFactory() {
67         private static final long serialVersionUID = 1L;
68
69         @Override
70         public IPointable createPointable() {
71             return new XSDateTimePointable();
72         }
73
74         @Override
75         public ITypeTraits getTypeTraits() {
76             return TYPE_TRAITS;
77         }
78     };
79
80     public void setCurrentDateTime() {
81         Calendar cal = Calendar.getInstance();
82         TimeZone tz = cal.getTimeZone();
83         int year = cal.get(Calendar.YEAR);
84         int month = cal.get(Calendar.MONTH);
85         int day = cal.get(Calendar.DAY_OF_MONTH);
86         int ms = cal.get(Calendar.MILLISECOND);
87         int tzOffsetInMs = tz.getOffset(
88                 cal.get(Calendar.ERA),
89                 year,
90                 month, 
91                 day, 
92                 cal.get(Calendar.DAY_OF_WEEK), 
93                 ms);
94         int tzOffsetInMin = tzOffsetInMs / 1000 / 60;
95         setDateTime(
96                 year,
97                 month + 1,
98                 day,
99                 cal.get(Calendar.HOUR_OF_DAY),
100                 cal.get(Calendar.MINUTE),
101                 cal.get(Calendar.SECOND) * 1000 + ms,
102                 tzOffsetInMin / 60,
103                 tzOffsetInMin % 60);
104     }
105     
106     public void setDateTime(long year, long month, long day, long hour, long minute, long milliSecond,
107             long timezoneHour, long timezoneMinute) {
108         setDateTime(bytes, start, year, month, day, hour, minute, milliSecond, timezoneHour, timezoneMinute);
109     }
110
111     public static void setDateTime(byte[] bytes, int start, long year, long month, long day, long hour, long minute,
112             long milliSecond, long timezoneHour, long timezoneMinute) {
113         ShortPointable.setShort(bytes, start + YEAR_OFFSET, (short) year);
114         BytePointable.setByte(bytes, start + MONTH_OFFSET, (byte) month);
115         BytePointable.setByte(bytes, start + DAY_OFFSET, (byte) day);
116         BytePointable.setByte(bytes, start + HOUR_OFFSET, (byte) hour);
117         BytePointable.setByte(bytes, start + MINUTE_OFFSET, (byte) minute);
118         IntegerPointable.setInteger(bytes, start + MILLISECOND_OFFSET, (int) milliSecond);
119         BytePointable.setByte(bytes, start + TIMEZONE_HOUR_OFFSET, (byte) timezoneHour);
120         BytePointable.setByte(bytes, start + TIMEZONE_MINUTE_OFFSET, (byte) timezoneMinute);
121     }
122
123     @Override
124     public long getYear() {
125         return getYear(bytes, start);
126     }
127
128     public static long getYear(byte[] bytes, int start) {
129         return (long) ShortPointable.getShort(bytes, start + YEAR_OFFSET);
130     }
131
132     @Override
133     public long getMonth() {
134         return getMonth(bytes, start);
135     }
136
137     public static long getMonth(byte[] bytes, int start) {
138         return (long) BytePointable.getByte(bytes, start + MONTH_OFFSET);
139     }
140
141     @Override
142     public long getDay() {
143         return getDay(bytes, start);
144     }
145
146     public static long getDay(byte[] bytes, int start) {
147         return (long) BytePointable.getByte(bytes, start + DAY_OFFSET);
148     }
149
150     @Override
151     public long getHour() {
152         return getHour(bytes, start);
153     }
154
155     public static long getHour(byte[] bytes, int start) {
156         return (long) BytePointable.getByte(bytes, start + HOUR_OFFSET);
157     }
158
159     @Override
160     public long getMinute() {
161         return getMinute(bytes, start);
162     }
163
164     public static long getMinute(byte[] bytes, int start) {
165         return (long) BytePointable.getByte(bytes, start + MINUTE_OFFSET);
166     }
167
168     @Override
169     public long getMilliSecond() {
170         return getMilliSecond(bytes, start);
171     }
172
173     public static long getMilliSecond(byte[] bytes, int start) {
174         return (long) IntegerPointable.getInteger(bytes, start + MILLISECOND_OFFSET);
175     }
176
177     @Override
178     public long getTimezoneHour() {
179         return getTimezoneHour(bytes, start);
180     }
181
182     public static long getTimezoneHour(byte[] bytes, int start) {
183         return (long) BytePointable.getByte(bytes, start + TIMEZONE_HOUR_OFFSET);
184     }
185
186     @Override
187     public long getTimezoneMinute() {
188         return getTimezoneMinute(bytes, start);
189     }
190
191     public static long getTimezoneMinute(byte[] bytes, int start) {
192         return (long) BytePointable.getByte(bytes, start + TIMEZONE_MINUTE_OFFSET);
193     }
194
195     @Override
196     public long getTimezone() {
197         return getTimezone(bytes, start);
198     }
199
200     public static long getTimezone(byte[] bytes, int start) {
201         return (getTimezoneHour(bytes, start) * 60 + getTimezoneMinute(bytes, start));
202     }
203
204     @Override
205     public long getYearMonth() {
206         return getYearMonth(bytes, start);
207     }
208
209     public static long getYearMonth(byte[] bytes, int start) {
210         return (getYear(bytes, start) * 12 + getMonth(bytes, start));
211     }
212
213     @Override
214     public long getDayTime() {
215         return getDayTime(bytes, start);
216     }
217
218     public static long getDayTime(byte[] bytes, int start) {
219         return (getDay(bytes, start) * DateTime.CHRONON_OF_DAY + getHour(bytes, start) * DateTime.CHRONON_OF_HOUR
220                 + getMinute(bytes, start) * DateTime.CHRONON_OF_MINUTE + getMilliSecond(bytes, start));
221     }
222
223     public String toString() {
224         return toString(bytes, start);
225     }
226
227     public static String toString(byte[] bytes, int start) {
228         final long millis = getMilliSecond(bytes, start);
229         return getYear(bytes, start)
230                 + "-"
231                 + getMonth(bytes, start)
232                 + "-"
233                 + getDay(bytes, start)
234                 + "T"
235                 + getHour(bytes, start)
236                 + ":"
237                 + getMinute(bytes, start)
238                 + ":"
239                 + millis / 1000
240                 + "."
241                 + millis % 1000
242                 + (getTimezoneHour(bytes, start) != DateTime.TIMEZONE_HOUR_NULL
243                         && getTimezoneMinute(bytes, start) != DateTime.TIMEZONE_MINUTE_NULL ? (getTimezoneHour(bytes,
244                         start) < 0 || getTimezoneMinute(bytes, start) < 0 ? "" : "+")
245                         + getTimezoneHour(bytes, start) + ":" + getTimezoneMinute(bytes, start) : "");
246     }
247
248 }