I want to convert a column which contains seconds (i.e 11549404) into days, hours, minutes, seconds
SELECT (myCol || ' second')::interval, 'HH24 hrs MI "minutes" SS "seconds"') AS duration
FROM public.myTable
Which returns the following;
"3208 hrs 10 minutes 04 seconds"
Whats the way to display it as days, hours, minutes seconds
Because some days has 23hours and others 25hours the result is not easy task (it is not possible, because don't know absolute value). interval type is a structure of months, days and seconds. The values are not automatically moved between these fields because mounts has different number of days, days can has different number of seconds. But you can do some normalization - there is a function justify_interval that expects so days has 24 hours every time:
postgres=# select justify_interval('3208 hrs 10 minutes 04 seconds'::interval);
+-------------------------+
| justify_interval |
+-------------------------+
| 4 mons 13 days 16:10:04 |
+-------------------------+
(1 row)
Related
I have a postgres database.
Is there an analogue of pg_size_pretty but for time? For example, if there are 3 seconds, then get "3 seconds", if several hours, then for example "3 hours 52 minutes 20 seconds".
Is there such a thing or are there any options how to implement it?
Right now my query looks like this.
select to_char(to_timestamp(ceil((finished_when - created_when) / 1000.0)), 'HH24 "hours" MI "minutes" SS "seconds"')
from nc_ei_sessions;
But I don't like that if the duration is 3 seconds, I will see 0 in hours and minutes
I've tried to subtract interval from timestamp, but I've got a wrong result in comparison to days via subtracting 2 dates.
E.g.:
select
(now::date - past::date) as days,
(now::date - past::date) / 365.25 as years,
justify_interval(now - past::date) as interval_test
from (
select '2020-09-17 00:00:01'::timestamp as now, '2010-09-17 00:00:01'::timestamp as past
) b;
gives results:
3653 days
10.0013 years
'10 years 1 mon 23 days' interval test
Could anyone help me to understand what is wrong with subtracting?
When I do it vice versa, it's ok:
select
(past::date + 3653)::date,
(past + interval '10 years')::date,
(past + 10*interval '1 year')::date,
(past + 10*12*interval '1 month')::date
from (
select '2020-09-17 00:00:01'::timestamp as now, '2010-09-17 00:00:01'::timestamp as past
) b;
all results give the same date '2020-09-17'
What I do wrong?
I am using PostgreSQL 10.5.
There is nothing wrong with subtracting. It is just that justify_interval doesn't do what you seem to expect. justify_interval uses 30 day months and 24 hour days. So 12 months becomes only 360 and 10 years only 3600 days. Leaving 53 days which is 1 (30 day) month and 23 days.
Edit
The justify_interval documentation on this page refers to justify_days and justify_hours which are directly above it which do mention the use of 30 days months and 24 hour days.
The justify functions do have to make these assumption because the interval type is a general length of time (it has no specific start and end). So the justify functions does not know over which specific months the interval was originally calculated.
The age function however does not take an interval it takes an end and a start so it actually knows which specific months and years are in that period.
Postgresql 8.4.
I'm new to this concept so if people could teach me I'd appreciate it.
For Obamacare, anyone that works 30 hours per week or more must be offered the same healthcare as is offered to any other worker. We can't afford that so we have to limit work hours for temp and part-timers. This is affecting the whole country.
I need to calculate the hours worked (doesn't matter if overtime,
regular time, double time, etc) between two dates, say Jan 1, 2014,
and Nov 1, 2014 (Saturday) for each custom week (which beings on Sunday), not the week as defined by Postgresql (which begins on Monday).
Each of my custom work weeks begins on Sunday and ends on Saturday.
I don't know if I have to include weeks where
they did not work at all in the average, but let's assume I do. Zero hours that week would draw down the average.
Table name is 'employeetime', date field is 'employeetime.stopdate', hours worked per day is in the field 'employeetime.hours', employeeid field is 'employeetime.empid'.
I'd prefer to do this in one query per employee and I will execute the query once per employee as I loop through employees. If not I'm open to suggestions. But I'd like to understand the SQL presented in the answer.
Currently EXTRACT(week from '2014-01-01') calculates the start of the week as a Monday, so that doesn't work for me. Link here.
How would I do that without doing, say a separate query for each week, per person? We have 200 people to process.
Thank you.
I have set up a table to match your format:
select * from employeetime order by date;
id date hours
1 2014-11-06 10
1 2014-11-07 3
1 2014-11-08 5
1 2014-11-09 3
1 2014-11-10 5
You can get the week starting on Sunday by shifting. Note, here the 9th is a Sunday, so that is where we want the boundary.
select *, extract(week from date + '1 day'::interval) as week
from employeetime
order by week;
id date hours week
1 2014-11-07 3 45
1 2014-11-06 10 45
1 2014-11-08 5 45
1 2014-11-09 3 46
1 2014-11-10 5 46
And now the week shifts on Sunday rather than Monday. From here, the query to get hours by week/employee would be simple:
select id, sum(hours) as hours, extract(week from date + '1 day'::interval) as week
from employeetime
group by id, week
order by id, week;
id hours week
1 18 45
1 8 46
I am building an app that deals with times and durations, and intersections between given units of time and start/end times in a database, for example:
Database:
Row # | start - end
Row 1 | 1:00 - 4:00
Row 2 | 3:00 - 6:00
I want to be able to select sums of time between two certain times, or GROUP BY an INTERVAL such that the returned recordset will have one row for each sum during a given interval, something like:
SELECT length( (start, end) ) WHERE (start, end) INTERSECTS (2:00,4:00)
(in this case (start,end) is a PERIOD which is a new data type in Postgres Temporal and pg9.2)
which would return
INTERVAL 3 HOURS
since Row 1 has two hours between 2:00 - 4:00 and Row 2 has one hour during that time.
further, i'd like to be able to:
SELECT "lower bound of start", length( (start, end) ) GROUP BY INTERVAL 1 HOUR
which i would like to return:
1:00 | 1
2:00 | 1
3:00 | 2
4:00 | 2
5:00 | 1
which shows one row for each hour during the given interval and the sum of time at the beginning of that interval
I think that the PERIOD type can be used for this, which is in Postgres Temporal and Postgres 9.2. However, these are not available on Heroku at this time as far as I can tell - So,
How can I enable these sorts of maths on Heroku?
Try running:
heroku addons:add heroku-postgresql:dev --version=9.2
That should give you the 9.2 version which has range types supported. As this is currently very alpha any feedback would be greatly appreciated at dod-feedback#heroku.com
How can I make an event occur every year for some selected days, Like starting 45 days then skip 15 days, then select 30 days then skip 30 days, then select 30 days then skip 30 days, then select 30 days then skip 30 days,then select 30 days then skip 30 days,then select 30 days then skip 30 days
RRULE:FREQ=YEARLY;BYYEARDAY=1,2,..,45,61,62,...,90,120,121....
Is this the right procedure?
combination of freq=yearly and byyearday is indeed the way forward, though it does not look ot be the case for you, you could also consider BYWEEKNO.