Reputation: 123
I've gotten as far as possible alone.
I need to replace the time within a datetime stamp in postgres.
This:
2015-11-20 08:00:00
Needs to be this:
2015-11-20 09:00:00
but for every day of the year (only the time changes)
this is what I have so far. (am i even close?)
UPDATE
events
SET
starttime = regexp_replace(starttime,
E’[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-0]{1}[8-8]{1}:[0-0]{1,2}:[0-0]{1,2}’,
E’[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-0]{1}[9-9]{1}:[0-0]{1,2}:[0-0]{1,2}’,‘g’)
WHERE
account_id = 9
AND starttime ~ E’[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-0]{1}[8-8]{1}:[0-0]{1,2}:[0-0]{1,2}’;
Upvotes: 2
Views: 2413
Reputation: 1516
I am hoping that your starttime
column is of timestamp
or timestamp with time zone
but in the event that I suspect it isn't it may need casting.
UPDATE events SET
starttime = starttime::timestamp + '1 hour'::interval
WHERE account_id = 9 AND extract(hour from starttime::timestamp) = 8;
As with Remi's answer, you should refer to the manual for more information on date time functions.
Upvotes: 4
Reputation: 5537
I'm not exactly sure what you're trying to do, but if the only thing, you're trying to do is to add one hour to starttime
timestamp, do not use regexp for date/time manipulations. Just don't.
Regexps are for manipulating text data, but timestamp is a TIMESTAMP
- it has it's internal structure which is more complex and allows precise manipulation, while it's text representation is only a "printed out" version of the original data. Again - TIMESTAMP
is postgresql datatype, so manipulate it directly, not via its "printed out" text form using regexp.
To be more specific, you should do something like this:
UPDATE
events
SET
starttime = starttime + interval '1 hour'
WHERE
account_id = 9
But if I didn't get it and you want to change only 08:00
times (as would your ill-formed update statement suggest), you can use EXTRACT(field FROM source)
:
UPDATE
events
SET
starttime = starttime + interval '1 hour'
WHERE
account_id = 9 AND EXTRACT(hour FROM starttime) = 8
(And similary for minutes or seconds, etc.)
Even if using regexps to manipulate TIMEDATE
is not very wise, your regexp expression is wrong in several ways:
you have 2 regexps in regexp_replace
call, which has form of regexp_replace(string, regexp, replacement)
. But you used regexp string even for replacement, which does this:
select regexp_replace('2015-11-20 08:00:00',
E'[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-0]{1}[8-8]{1}:[0-0]{1,2}:[0-0]{1,2}',
E'[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-0]{1}[9-9]{1}:[0-0]{1,2}:[0-0]{1,2}', 'g');
regexp_replace
-----------------------------------------------------------------------
[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-0]{1}[9-9]{1}:[0-0]{1,2}:[0-0]{1,2}
So you can see that you just replaced everything with the replacement
string. Bettew replacement
string would have references to groups matched by a regexp
, which brings us to second problem:
your regexp expression does not have groups in parenthesis. If I correct that and add references to these groups in replacement
string, you'll get:
select regexp_replace('2015-11-20 08:00:00',
E'([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}) ([0-0]{1})([8-8]{1}):([0-0]{1,2}):([0-0]{1,2})',
E'\\1-\\2-\\3 \\4\\5:\\6:\\7', 'g');
regexp_replace
---------------------
2015-11-20 08:00:00
which looks almost good. But since you want to replace the 08:00
, let's change it to:
select regexp_replace('2015-11-20 08:00:00',
E'([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}) ([0-0]{1})([8-8]{1}):([0-0]{1,2}):([0-0]{1,2})',
E'\\1-\\2-\\3 09:00:00', 'g');
regexp_replace
---------------------
2015-11-20 09:00:00
this is not exactly a problem, but using [0-0]{1}
to match a zero (or other single character) is unnecessary, plain 0
would suffice, so I just added the 08:00:00
string exactly. (You can change it to [01][0-9]:00:00
to match every hour, or [0-9]{2}:[0-9]{2}:[0-9]{2}
to match any time)
select regexp_replace('2015-11-20 08:00:00',
E'([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}) 08:00:00',
E'\\1-\\2-\\3 09:00:00', 'g');
regexp_replace
---------------------
2015-11-20 09:00:00
Upvotes: 4
Reputation: 15222
The documentation is very helpful for this topic.
Typing add 1 hour timestamp
into the search box at:
http://www.postgresql.org/docs/9.4/interactive/index.html
yields the following page as the first hit:
http://www.postgresql.org/docs/9.4/static/functions-datetime.html
So you can do something like
timestamp '2001-09-28 01:00' + interval '1 hour'
Also if your source is a column (namely mydatecolumn) , this could become:
mydatecolumn::timestamp + interval '1 hour'
Upvotes: 4