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 @ 44924

History | View | Annotate | Download (9.43 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
            "EXTRACT( {{time_field}} FROM time_expression)",
157
            new String[]{
158
              "field - ",
159
              "date - a string with a date"
160
            },
161
            "OBJECT",
162
            true
163
    );
164
  }
165

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

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

    
229
  }
230

    
231
}