1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * rasqal_expr_datetimes.c - Rasqal date and time expression functions
4 *
5 * Copyright (C) 2010, David Beckett http://www.dajobe.org/
6 *
7 * This package is Free Software and part of Redland http://librdf.org/
8 *
9 * It is licensed under the following three licenses as alternatives:
10 * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
11 * 2. GNU General Public License (GPL) V2 or any newer version
12 * 3. Apache License, V2.0 or any newer version
13 *
14 * You may not use this file except in compliance with at least one of
15 * the above three licenses.
16 *
17 * See LICENSE.html or LICENSE.txt at the top of this package for the
18 * complete terms and further detail along with the license texts for
19 * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
20 *
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <rasqal_config.h>
26 #endif
27
28 #ifdef WIN32
29 #include <win32_rasqal_config.h>
30 #endif
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <ctype.h>
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif
38 #include <stdarg.h>
39
40 #include "rasqal.h"
41 #include "rasqal_internal.h"
42
43
44 #define DEBUG_FH stderr
45
46
47 /*
48 * rasqal_expression_evaluate_now:
49 * @e: The expression to evaluate.
50 * @eval_context: Evaluation context
51 *
52 * INTERNAL - Evaluate RASQAL_EXPR_NOW, RASQAL_EXPR_DATETIME expressions.
53 *
54 * Return value: A #rasqal_literal value or NULL on failure.
55 */
56 rasqal_literal*
rasqal_expression_evaluate_now(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)57 rasqal_expression_evaluate_now(rasqal_expression *e,
58 rasqal_evaluation_context *eval_context,
59 int *error_p)
60 {
61 rasqal_world* world = eval_context->world;
62 struct timeval *tv;
63 rasqal_xsd_datetime* dt;
64
65 tv = rasqal_world_get_now_timeval(world);
66 if(!tv)
67 goto failed;
68
69 dt = rasqal_new_xsd_datetime_from_timeval(world, tv);
70 if(!dt)
71 goto failed;
72
73 return rasqal_new_datetime_literal_from_datetime(world, dt);
74
75 failed:
76 if(error_p)
77 *error_p = 1;
78
79 return NULL;
80 }
81
82
83 /*
84 * rasqal_expression_evaluate_to_unixtime:
85 * @e: The expression to evaluate.
86 * @eval_context: Evaluation context
87 *
88 * INTERNAL - Evaluate LAQRS RASQAL_EXPR_TO_UNIXTIME (datetime) expression.
89 *
90 * Return value: A #rasqal_literal integer value or NULL on failure.
91 */
92 rasqal_literal*
rasqal_expression_evaluate_to_unixtime(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)93 rasqal_expression_evaluate_to_unixtime(rasqal_expression *e,
94 rasqal_evaluation_context *eval_context,
95 int *error_p)
96 {
97 rasqal_world* world = eval_context->world;
98 rasqal_literal* l;
99 time_t unixtime = 0;
100
101 l = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
102 if((error_p && *error_p) || !l)
103 goto failed;
104
105 if(l->type != RASQAL_LITERAL_DATETIME)
106 goto failed;
107
108 unixtime = rasqal_xsd_datetime_get_as_unixtime(l->value.datetime);
109 rasqal_free_literal(l); l = NULL;
110 if(!unixtime)
111 goto failed;
112
113 return rasqal_new_numeric_literal_from_long(world, RASQAL_LITERAL_INTEGER,
114 unixtime);
115
116 failed:
117 if(error_p)
118 *error_p = 1;
119
120 if(l)
121 rasqal_free_literal(l);
122 return NULL;
123
124 }
125
126
127 /*
128 * rasqal_expression_evaluate_from_unixtime:
129 * @e: The expression to evaluate.
130 * @eval_context: Evaluation context
131 *
132 * INTERNAL - Evaluate LAQRS RASQAL_EXPR_FROM_UNIXTIME (integer expr) expression.
133 *
134 * Return value: A #rasqal_literal datetime value or NULL on failure.
135 */
136 rasqal_literal*
rasqal_expression_evaluate_from_unixtime(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)137 rasqal_expression_evaluate_from_unixtime(rasqal_expression *e,
138 rasqal_evaluation_context *eval_context,
139 int *error_p)
140 {
141 rasqal_world* world = eval_context->world;
142 rasqal_literal* l;
143 int unixtime = 0;
144 rasqal_xsd_datetime* dt;
145
146 l = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
147 if((error_p && *error_p) || !l)
148 goto failed;
149
150 unixtime = rasqal_literal_as_integer(l, error_p);
151 rasqal_free_literal(l); l = NULL;
152 if(error_p && *error_p)
153 goto failed;
154
155 dt = rasqal_new_xsd_datetime_from_unixtime(world, unixtime);
156 if(!dt)
157 goto failed;
158
159 return rasqal_new_datetime_literal_from_datetime(world, dt);
160
161 failed:
162 if(error_p)
163 *error_p = 1;
164
165 if(l)
166 rasqal_free_literal(l);
167 return NULL;
168
169 }
170
171
172 /*
173 * rasqal_expression_evaluate_datetime_part:
174 * @e: The expression to evaluate.
175 * @eval_context: Evaluation context
176 *
177 * INTERNAL - Evaluate SPARQL 1.1 RASQAL_EXPR_YEAR, RASQAL_EXPR_MONTH,
178 * RASQAL_EXPR_DAY, RASQAL_EXPR_HOURS, RASQAL_EXPR_MINUTES,
179 * RASQAL_EXPR_SECONDS (datetime) expressions.
180 *
181 * Return value: A #rasqal_literal integer value or NULL on failure.
182 */
183 rasqal_literal*
rasqal_expression_evaluate_datetime_part(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)184 rasqal_expression_evaluate_datetime_part(rasqal_expression *e,
185 rasqal_evaluation_context *eval_context,
186 int *error_p)
187 {
188 rasqal_world* world = eval_context->world;
189 rasqal_literal* l;
190 int i;
191
192 l = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
193 if((error_p && *error_p) || !l)
194 goto failed;
195
196 if(l->type != RASQAL_LITERAL_DATETIME)
197 goto failed;
198
199 /* SECONDS accessor has decimal results and includes microseconds */
200 if(e->op == RASQAL_EXPR_SECONDS) {
201 rasqal_xsd_decimal* dec;
202 rasqal_literal* result = NULL;
203
204 dec = rasqal_xsd_datetime_get_seconds_as_decimal(world,
205 l->value.datetime);
206 rasqal_free_literal(l);
207 if(dec) {
208 result = rasqal_new_decimal_literal_from_decimal(world, NULL, dec);
209 if(!result)
210 rasqal_free_xsd_decimal(dec);
211 }
212
213 if(!result)
214 goto failed;
215
216 return result;
217 }
218
219 /* The remaining accessors have xsd:integer results */
220 if(e->op == RASQAL_EXPR_YEAR)
221 i = l->value.datetime->year;
222 else if(e->op == RASQAL_EXPR_MONTH)
223 i = l->value.datetime->month;
224 else if(e->op == RASQAL_EXPR_DAY)
225 i = l->value.datetime->day;
226 else if(e->op == RASQAL_EXPR_HOURS)
227 i = l->value.datetime->hour;
228 else if(e->op == RASQAL_EXPR_MINUTES)
229 i = l->value.datetime->minute;
230 else if(e->op == RASQAL_EXPR_SECONDS)
231 i = l->value.datetime->second;
232 else
233 i = 0;
234
235 rasqal_free_literal(l);
236
237 return rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, i);
238
239
240 failed:
241 if(error_p)
242 *error_p = 1;
243
244 return NULL;
245 }
246
247
248 /*
249 * rasqal_expression_evaluate_datetime_timezone:
250 * @e: The expression to evaluate.
251 * @eval_context: Evaluation context
252 *
253 * INTERNAL - Evaluate SPARQL 1.1 RASQAL_EXPR_TIMEZONE (datetime) expression.
254 *
255 * Return value: A #rasqal_literal xsd:dayTimeDuration value or NULL on failure.
256 */
257 rasqal_literal*
rasqal_expression_evaluate_datetime_timezone(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)258 rasqal_expression_evaluate_datetime_timezone(rasqal_expression *e,
259 rasqal_evaluation_context *eval_context,
260 int *error_p)
261 {
262 rasqal_world* world = eval_context->world;
263 rasqal_literal* l;
264 const unsigned char* s = NULL;
265 raptor_uri* dt_uri;
266
267 l = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
268 if((error_p && *error_p) || !l)
269 goto failed;
270
271 if(l->type != RASQAL_LITERAL_DATETIME)
272 goto failed;
273
274 s = RASQAL_GOOD_CAST(const unsigned char*, rasqal_xsd_datetime_get_timezone_as_counted_string(l->value.datetime, NULL));
275 if(!s)
276 goto failed;
277
278 dt_uri = raptor_new_uri_from_uri_local_name(world->raptor_world_ptr,
279 world->xsd_namespace_uri,
280 RASQAL_GOOD_CAST(unsigned char*, "dayTimeDuration"));
281 if(!dt_uri)
282 goto failed;
283
284 rasqal_free_literal(l);
285
286 /* after this s and dt_uri are owned by the result literal */
287 return rasqal_new_string_literal(world, s, NULL, dt_uri, NULL);
288
289 failed:
290 if(error_p)
291 *error_p = 1;
292
293 if(s)
294 RASQAL_FREE(char*, s);
295
296 if(l)
297 rasqal_free_literal(l);
298
299 return NULL;
300 }
301
302
303 /*
304 * rasqal_expression_evaluate_datetime_tz:
305 * @e: The expression to evaluate.
306 * @eval_context: Evaluation context
307 *
308 * INTERNAL - Evaluate SPARQL 1.1 RASQAL_EXPR_TZ (datetime) expression.
309 *
310 * Return value: A #rasqal_literal string value or NULL on failure.
311 */
312 rasqal_literal*
rasqal_expression_evaluate_datetime_tz(rasqal_expression * e,rasqal_evaluation_context * eval_context,int * error_p)313 rasqal_expression_evaluate_datetime_tz(rasqal_expression *e,
314 rasqal_evaluation_context *eval_context,
315 int *error_p)
316 {
317 rasqal_world* world = eval_context->world;
318 rasqal_literal* l;
319 const unsigned char* s = NULL;
320
321 l = rasqal_expression_evaluate2(e->arg1, eval_context, error_p);
322 if((error_p && *error_p) || !l)
323 goto failed;
324
325 if(l->type != RASQAL_LITERAL_DATETIME)
326 goto failed;
327
328 #define TIMEZONE_STRING_LEN 7
329
330 s = RASQAL_GOOD_CAST(const unsigned char*, rasqal_xsd_datetime_get_tz_as_counted_string(l->value.datetime, NULL));
331 if(!s)
332 goto failed;
333
334 rasqal_free_literal(l);
335
336 /* after this s is owned by the result literal */
337 return rasqal_new_string_literal(world, s, NULL, NULL, NULL);
338
339 failed:
340 if(error_p)
341 *error_p = 1;
342
343 if(l)
344 rasqal_free_literal(l);
345
346 return NULL;
347 }
348