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