Reputation:
In a form we have, people will enter an age by first specifying a category (minutes, hours, days, months, years) and then secondarily entering an integer value. The problem with this practice is that ages become inconsistent - 18 months is greater than 1 year, this makes statistical analysis difficult.
Internally I need to store this data not as two integers (as it is currently stored) but as an interval and an integer. The second integer indicates the original unit.
Here is the question: what is the simple method for telling postgreSQL to return this interval back as the time it was entered as? So for instance, the user enters: 18 months. Right now, it will return it as 1 year, 6 months. -- can't redisplay that on the form. I know based on the other integer what they entered it as, so there will be no fractional component - i.e. if they entered it in days, there will be no hours, etc.
Ideally it would be something like
SELECT as_time((person.age).value,'months')
Note that these intervals are entered as-is, so the months would not ever be anything other than the 30-day interval 'months' (representational months). If need be I can use a plpgsql function for it, since I'll need to do a lookup on the time type code; but the strict requirement in all cases is that if they entered some time, they get back exactly that time, no rounding, no 'correction', etc.
Upvotes: 0
Views: 931
Reputation: 658927
WITH x(unit, t) AS (
VALUES
(1, interval '1 month')
,(1, interval '2 month')
,(1, interval '3 month')
,(1, interval '12 month')
,(1, interval '13 month')
,(1, interval '18 month')
,(1, interval '24 month')
,(1, interval '30 month')
,(1, interval '300 month')
,(2, interval '1 year')
,(2, interval '2 year')
,(2, interval '5 year')
,(2, interval '100 year')
)
SELECT CASE unit
WHEN 1 THEN EXTRACT(year FROM t)::int * 12
+ EXTRACT(month FROM t)::int
WHEN 2 THEN EXTRACT(year FROM t)::int
ELSE -1 -- should not occour
END AS units
,CASE unit
WHEN 1 THEN 'months'
WHEN 2 THEN 'years'
ELSE 'unknown' -- should not occour
END as unit
FROM x;
You could try and extract the epoch
value (count of seconds) and convert it - like @Magnus demonstrates here, but months and years are justified for the irregular nature of months, so the calculation would be off with bigger intervals.
Upvotes: 1