Обсуждение: Function to offset current timestamp

Поиск
Список
Период
Сортировка

Function to offset current timestamp

От
Dan Harris
Дата:
I'm trying to write a function that can do a select on an integer value from a
table and subtract that value from current_timestamp.

Let's say I have a table called users and a field called tz_offset..

I want my function to do something like :

select current_timestamp - '( select tz_offset from users where userid = ? )
hours'::interval

Obviously this syntax is incorrect, but I'm not quite sure how to do the
subquery and make the integer result of it part of the quoted interval expression.

Any tips?

Thx

Re: Function to offset current timestamp

От
Dan Harris
Дата:
Dan Harris wrote:
> I'm trying to write a function that can do a select on an integer value
> from a table and subtract that value from current_timestamp.
>
> Let's say I have a table called users and a field called tz_offset..
>
> I want my function to do something like :
>
> select current_timestamp - '( select tz_offset from users where userid =
> ? ) hours'::interval
>
> Obviously this syntax is incorrect, but I'm not quite sure how to do the
> subquery and make the integer result of it part of the quoted interval
> expression.
>
> Any tips?
>
> Thx
>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Have you searched our list archives?
>
>               http://archives.postgresql.org

ok, sorry to reply to my own message, but I figured out a way:

select current_timestamp - ( select tz_offset from users where userid = ? ) * '1
hour'::interval;



Re: Function to offset current timestamp

От
Steve Crawford
Дата:
Dan Harris wrote:
> I'm trying to write a function that can do a select on an integer value
> from a table and subtract that value from current_timestamp.
>
> Let's say I have a table called users and a field called tz_offset..
>
> I want my function to do something like :
>
> select current_timestamp - '( select tz_offset from users where userid =
> ? ) hours'::interval
>
> Obviously this syntax is incorrect, but I'm not quite sure how to do the
> subquery and make the integer result of it part of the quoted interval
> expression.
>
> Any tips?


You don't need to make it part of the quoted expression - just multiply
an interval by your integer. Using your version, try something like:

select current_timestamp - '1 hour'::interval * ( select tz_offset from
users where userid = ? )

But this is actually wrong because the returned time is still in your
current timezone - just offset by X hours. If you store this value and
end up displaying it in another timezone you will get unexpected
results. Additionally, it won't give you the desired result in the
vicinity of DST change. If your server is Pacific time and the user is
Eastern, the East-coasters will have jumped forward/backward while your
server hasn't.

Instead, you might switch the timezone to whatever zone is correct for
the specific user.

-- Start transaction to keep timestamps the same
test=# begin;
BEGIN

-- Get current time (server default is PST8PDT - currently -07 hours)
test=# select current_timestamp;
          timestamptz
-------------------------------
 2007-06-01 10:54:17.627987-07

-- Subtract three hours to get pseudo-east-coast time. Really we got
-- three-hours earlier in Pacific time (still -07).
test=# select current_timestamp - 3 * '1 hour'::interval;
           ?column?
-------------------------------
 2007-06-01 07:54:17.627987-07

-- Set the timezone to Eastern US
test=# set timezone to EST5EDT;
SET

-- Time doesn't change - it is just displayed appropriately
-- for the user (Eastern Daylight Time = -04).
test=# select current_timestamp;
          timestamptz
-------------------------------
 2007-06-01 13:54:17.627987-04


I'm not quite sure how to change session timezone based on a query. This
doesn't work:
set timezone to (select timezone from users where userid = ?);

Another possibility is to use "at timezone" which can be handled from a
query:
test=# select current_timestamp at timezone (select 'CST6CDT');
          timezone
----------------------------
 2007-06-01 13:23:59.234811

But beware. This query appears to strip off the timezone information and
return a timestamp without timezone. This may be fine for display
purposes but might not be if you are storing the value somewhere.

Cheers,
Steve

Re: Function to offset current timestamp

От
Dan Harris
Дата:
Steve Crawford wrote:
> Dan Harris wrote:
>> I'm trying to write a function that can do a select on an integer value
>> from a table and subtract that value from current_timestamp.
>>
>> Let's say I have a table called users and a field called tz_offset..
>>
>> I want my function to do something like :
>>
>> select current_timestamp - '( select tz_offset from users where userid =
>> ? ) hours'::interval
>>
>> Obviously this syntax is incorrect, but I'm not quite sure how to do the
>> subquery and make the integer result of it part of the quoted interval
>> expression.
>>
>> Any tips?
>
>
> You don't need to make it part of the quoted expression - just multiply
> an interval by your integer. Using your version, try something like:
>
> select current_timestamp - '1 hour'::interval * ( select tz_offset from
> users where userid = ? )
>
> But this is actually wrong because the returned time is still in your
> current timezone - just offset by X hours.

Thanks for the extra explanation here.  I think I'll be OK because the timezone
offset comes directly from the browser.  I grab it via javascript and as long as
their system timezone offset is set correctly, the dates will be displayed
relative to them.  I do understand that I will have to do more work if I want to
display their dates to other users in different timezones correctly.

-Dan