Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.lib / org.gvsig.expressionevaluator.lib.impl / src / main / java / org / gvsig / expressionevaluator / impl / function / date / ExtractFunction.java @ 44750

History | View | Annotate | Download (9.15 KB)

1
package org.gvsig.expressionevaluator.impl.function.date;
2

    
3
import java.time.LocalDateTime;
4
import java.time.ZoneId;
5
import java.time.temporal.ChronoField;
6
import java.time.temporal.IsoFields;
7
import java.util.Date;
8
import org.apache.commons.lang3.Range;
9
import org.gvsig.expressionevaluator.Interpreter;
10
import org.gvsig.expressionevaluator.spi.AbstractFunction;
11
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_EXTRACT;
12

    
13
public class ExtractFunction extends AbstractFunction {
14

    
15
  public ExtractFunction() {
16
    super("Date", FUNCTION_EXTRACT, Range.is(2),
17
            "The extract function retrieves subfields such as year or hour from date/time values. source must be a value expression of type timestamp, time, or interval. (Expressions of type date are cast to timestamp and can therefore be used as well.) field is an identifier or string that selects what field to extract from the source value. The extract function returns values of type double precision. The following are valid field names:\n"
18
            + "\n"
19
            + "century (not supported)\n"
20
            + "\n"
21
            + "    The century\n"
22
            + "\n"
23
            + "    EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13');\n"
24
            + "    Result: 20\n"
25
            + "    EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40');\n"
26
            + "    Result: 21\n"
27
            + "\n"
28
            + "    The first century starts at 0001-01-01 00:00:00 AD, although they did not know it at the time. This definition applies to all Gregorian calendar countries. There is no century number 0, you go from -1 century to 1 century. If you disagree with this, please write your complaint to: Pope, Cathedral Saint-Peter of Roma, Vatican.\n"
29
            + "\n"
30
            + "day\n"
31
            + "\n"
32
            + "    For timestamp values, the day (of the month) field (1 - 31) ; for interval values, the number of days\n"
33
            + "\n"
34
            + "    EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40');\n"
35
            + "    Result: 16\n"
36
            + "\n"
37
            + "decade (not supported)\n"
38
            + "\n"
39
            + "    The year field divided by 10\n"
40
            + "\n"
41
            + "    EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');\n"
42
            + "    Result: 200\n"
43
            + "\n"
44
            + "dow\n"
45
            + "\n"
46
            + "    The day of the week as Sunday (0) to Saturday (6)\n"
47
            + "\n"
48
            + "    EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');\n"
49
            + "    Result: 5\n"
50
            + "\n"
51
            + "doy\n"
52
            + "\n"
53
            + "    The day of the year (1 - 365/366)\n"
54
            + "\n"
55
            + "    EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');\n"
56
            + "    Result: 47\n"
57
            + "\n"
58
            + "hour\n"
59
            + "\n"
60
            + "    The hour field (0 - 23)\n"
61
            + "\n"
62
            + "    EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');\n"
63
            + "    Result: 20\n"
64
            + "\n"
65
            + "isodow\n"
66
            + "\n"
67
            + "    The day of the week as Monday (1) to Sunday (7)\n"
68
            + "\n"
69
            + "    EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');\n"
70
            + "    Result: 7\n"
71
            + "\n"
72
            + "    This is identical to dow except for Sunday. This matches the ISO 8601 day of the week numbering.\n"
73
            + "\n"
74
            + "isoyear (not supported)\n"
75
            + "\n"
76
            + "    The ISO 8601 week-numbering year that the date falls in (not applicable to intervals)\n"
77
            + "\n"
78
            + "    EXTRACT(ISOYEAR FROM DATE '2006-01-01');\n"
79
            + "    Result: 2005\n"
80
            + "    EXTRACT(ISOYEAR FROM DATE '2006-01-02');\n"
81
            + "    Result: 2006\n"
82
            + "\n"
83
            + "    Each ISO 8601 week-numbering year begins with the Monday of the week containing the 4th of January, so in early January or late December the ISO year may be different from the Gregorian year. See the week field for more information.\n"
84
            + "\n"
85
            + "\n"
86
            + "microseconds (not supported)\n"
87
            + "\n"
88
            + "    The seconds field, including fractional parts, multiplied by 1 000 000; note that this includes full seconds\n"
89
            + "\n"
90
            + "    EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');\n"
91
            + "    Result: 28500000\n"
92
            + "\n"
93
            + "millennium (not supported)\n"
94
            + "\n"
95
            + "    The millennium\n"
96
            + "\n"
97
            + "    EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40');\n"
98
            + "    Result: 3\n"
99
            + "\n"
100
            + "    Years in the 1900s are in the second millennium. The third millennium started January 1, 2001.\n"
101
            + "\n"
102
            + "milliseconds\n"
103
            + "\n"
104
            + "    The seconds field, including fractional parts, multiplied by 1000. Note that this includes full seconds.\n"
105
            + "\n"
106
            + "    EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');\n"
107
            + "    Result: 28500\n"
108
            + "\n"
109
            + "minute\n"
110
            + "\n"
111
            + "    The minutes field (0 - 59)\n"
112
            + "\n"
113
            + "    EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40');\n"
114
            + "    Result: 38\n"
115
            + "\n"
116
            + "month\n"
117
            + "\n"
118
            + "    For timestamp values, the number of the month within the year (1 - 12) ; for interval values, the number of months, modulo 12 (0 - 11)\n"
119
            + "\n"
120
            + "    EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40');\n"
121
            + "    Result: 2\n"
122
            + "\n"
123
            + "quarter\n"
124
            + "\n"
125
            + "    The quarter of the year (1 - 4) that the date is in\n"
126
            + "\n"
127
            + "    EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');\n"
128
            + "    Result: 1\n"
129
            + "\n"
130
            + "second\n"
131
            + "\n"
132
            + "    The seconds field, including fractional parts (0 - 59[1])\n"
133
            + "\n"
134
            + "    EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40');\n"
135
            + "    Result: 40\n"
136
            + "\n"
137
            + "    EXTRACT(SECOND FROM TIME '17:12:28.5');\n"
138
            + "    Result: 28.5\n"
139
            + "\n"
140
            + "week\n"
141
            + "\n"
142
            + "    The number of the ISO 8601 week-numbering week of the year. By definition, ISO weeks start on Mondays and the first week of a year contains January 4 of that year. In other words, the first Thursday of a year is in week 1 of that year.\n"
143
            + "\n"
144
            + "    In the ISO week-numbering system, it is possible for early-January dates to be part of the 52nd or 53rd week of the previous year, and for late-December dates to be part of the first week of the next year. For example, 2005-01-01 is part of the 53rd week of year 2004, and 2006-01-01 is part of the 52nd week of year 2005, while 2012-12-31 is part of the first week of 2013. It's recommended to use the isoyear field together with week to get consistent results.\n"
145
            + "\n"
146
            + "    EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');\n"
147
            + "    Result: 7\n"
148
            + "\n"
149
            + "year\n"
150
            + "\n"
151
            + "    The year field. Keep in mind there is no 0 AD, so subtracting BC years from AD years should be done with care.\n"
152
            + "\n"
153
            + "    EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');\n"
154
            + "    Result: 2001\n"
155
            + "",
156
            FUNCTION_EXTRACT + "({{field}}, date)",
157
            new String[]{
158
              "field - ",
159
              "date - a string with a date"
160
            },
161
            "OBJECT"
162
    );
163
  }
164

    
165
  @Override
166
  public boolean allowConstantFolding() {
167
    return true;
168
  }
169

    
170
  @Override
171
  public Object call(Interpreter interpreter, Object[] args) {
172
    String field = getStr(args, 0).toLowerCase();
173
    Date date = (Date) getObject(args, 1);
174
    LocalDateTime time = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
175
    Number r = null;
176
    switch(field) {
177
      case "day":
178
        r = time.getDayOfMonth();
179
        break;
180
      case "dow":
181
        r = date.getDay();
182
        break;
183
      case "hour":
184
        r = time.getHour();
185
        break;
186
      case "isodow":
187
        r = time.getDayOfWeek().getValue();
188
        break;
189
      case "minute":
190
        r = time.getMinute();
191
        break;
192
      case "month":
193
        r = time.getDayOfMonth();
194
        break;
195
      case "second":
196
        r = time.getSecond() + (time.getNano()/1000000000.0);
197
        break;
198
      case "week":
199
        r = time.get(ChronoField.ALIGNED_WEEK_OF_YEAR);
200
        break;
201
      case "year":
202
        r = time.getYear();
203
        break;
204
      case "quarter":
205
        r = time.get(IsoFields.QUARTER_OF_YEAR);
206
        break;
207
      case "doy":
208
        r = time.get(ChronoField.DAY_OF_YEAR);
209
        break;
210
      case "decade":
211
      case "century":
212
      case "isoyear":
213
      case "microseconds":
214
      case "millennium":
215
      case "milliseconds":
216
      default:
217
        throw new RuntimeException("field '"+field+"' not supported.");
218
    }
219
    return r;
220

    
221
  }
222

    
223
}