Revision 6218
Added by Aaron Marcuse-Kubitza over 12 years ago
schemas/py_functions.sql | ||
---|---|---|
40 | 40 |
ALTER FUNCTION py_functions._date(date timestamp with time zone) OWNER TO bien; |
41 | 41 |
|
42 | 42 |
-- |
43 |
-- Name: _date(text, text, text, text); Type: FUNCTION; Schema: py_functions; Owner: bien
|
|
43 |
-- Name: _date(text, text, text); Type: FUNCTION; Schema: py_functions; Owner: bien |
|
44 | 44 |
-- |
45 | 45 |
|
46 |
CREATE FUNCTION _date(date text DEFAULT NULL::text, year text DEFAULT NULL::text, month text DEFAULT NULL::text, day text DEFAULT NULL::text) RETURNS text
|
|
46 |
CREATE FUNCTION _date(year text DEFAULT NULL::text, month text DEFAULT NULL::text, day text DEFAULT NULL::text) RETURNS text |
|
47 | 47 |
LANGUAGE plpython3u IMMUTABLE |
48 | 48 |
AS $$ |
49 | 49 |
global date, year, month, day |
50 | 50 |
|
51 | 51 |
import datetime |
52 |
import dateutil.tz |
|
53 | 52 |
|
54 | 53 |
def e_msg(e): return e.args[0].rstrip() |
55 | 54 |
|
56 |
def e_str(e): return e.__class__.__name__+': '+e_msg(e) |
|
55 |
# Year is required |
|
56 |
if year == None: |
|
57 |
if month == None and day == None: return None # entire date is empty |
|
58 |
else: raise AssertionError( |
|
59 |
'null value in column "year" violates not-null constraint') |
|
57 | 60 |
|
58 |
def raise_invalid_value(cause, value):
|
|
59 |
raise ValueError('invalid input value: "'+str(value)+'"\nDETAIL: '
|
|
60 |
+e_str(cause))
|
|
61 |
# Convert month name to number
|
|
62 |
if month != None and not month.isdigit(): # month is name
|
|
63 |
month = str(datetime.datetime.strptime(month, '%b').month)
|
|
61 | 64 |
|
62 |
utc = dateutil.tz.tzutc() |
|
65 |
if month == None: month = 1 |
|
66 |
if day == None: day = 1 |
|
67 |
year, month, day = map(int, (year, month, day)) |
|
63 | 68 |
|
64 |
def naive2utc(datetime_): |
|
65 |
assert datetime_.tzinfo == None |
|
66 |
return datetime_.replace(tzinfo=utc) |
|
69 |
for try_num in range(2): |
|
70 |
try: |
|
71 |
date = datetime.date(year, month, day) |
|
72 |
break |
|
73 |
except ValueError as e: |
|
74 |
if try_num > 0: raise # exception still raised after retry |
|
75 |
msg = e_msg(e) |
|
76 |
if msg == 'month must be in 1..12': # try swapping month and day |
|
77 |
month, day = day, month |
|
78 |
else: raise |
|
67 | 79 |
|
68 |
def from_timestamp(utc_timestamp): |
|
69 |
return naive2utc(datetime.datetime.utcfromtimestamp(utc_timestamp)) |
|
70 |
|
|
71 |
epoch = from_timestamp(0) |
|
72 |
|
|
73 |
def strtotime(str_, default=epoch): |
|
74 |
import dateutil.parser |
|
75 |
return dateutil.parser.parse(str_, default=default) |
|
76 |
|
|
77 |
if date != None: |
|
78 |
str_ = date |
|
79 |
try: year = float(str_) |
|
80 |
except ValueError: |
|
81 |
try: date = strtotime(str_) |
|
82 |
except ImportError: return str_ |
|
83 |
except ValueError as e: raise_invalid_value(e, str_) |
|
84 |
else: date = (datetime.date(int(year), 1, 1) + |
|
85 |
datetime.timedelta(round((year % 1.)*365))) |
|
86 |
else: |
|
87 |
# Year is required |
|
88 |
if year == None: |
|
89 |
if month == None and day == None: return None # entire date is empty |
|
90 |
else: raise AssertionError( |
|
91 |
'null value in column "year" violates not-null constraint') |
|
92 |
|
|
93 |
# Convert month name to number |
|
94 |
if month != None and not month.isdigit(): # month is name |
|
95 |
month = str(strtotime(month).month) |
|
96 |
|
|
97 |
if month == None: month = 1 |
|
98 |
if day == None: day = 1 |
|
99 |
year, month, day = map(int, (year, month, day)) |
|
100 |
|
|
101 |
for try_num in range(2): |
|
102 |
try: |
|
103 |
date = datetime.date(year, month, day) |
|
104 |
break |
|
105 |
except ValueError as e: |
|
106 |
if try_num > 0: raise # exception still raised after retry |
|
107 |
msg = e_msg(e) |
|
108 |
if msg == 'month must be in 1..12': # try swapping month and day |
|
109 |
month, day = day, month |
|
110 |
else: raise |
|
111 |
|
|
112 | 80 |
return str(date) |
113 | 81 |
$$; |
114 | 82 |
|
115 | 83 |
|
116 |
ALTER FUNCTION py_functions._date(date text, year text, month text, day text) OWNER TO bien;
|
|
84 |
ALTER FUNCTION py_functions._date(year text, month text, day text) OWNER TO bien; |
|
117 | 85 |
|
118 | 86 |
-- |
119 | 87 |
-- Name: _dateRangeEnd(text); Type: FUNCTION; Schema: py_functions; Owner: bien |
Also available in: Unified diff
schemas/py_functions.sql: _date(): Removed features that require dateutil, which is not available under plpython3u. This includes removing the now-unused date string parameter.