Reputation: 35149
I have a table that has the column hour
that is not in the right timestamp
format:
hour
---------------------
2014-12-06-01:44:35
2014-12-06-01:44:35
2014-12-06-01:44:35
2014-12-06-01:44:35
2014-12-06-01:44:35
2014-12-06-01:44:35
I want to replace -
with ' '
in the middle, so it would look like this:
hour
---------------------
2014-12-06 01:44:35
2014-12-06 01:44:35
2014-12-06 01:44:35
2014-12-06 01:44:35
2014-12-06 01:44:35
2014-12-06 01:44:35
I've tried this:
select regexp_replace(hour, '\d{4}-\d{2}-\d{2}(-)\d{2}:\d{2}:\d{2}', ' ')
from my_table;
But unfortunately it doesn't make any difference.
I'm using Redshift, not PostgreSQL.
Upvotes: 3
Views: 2158
Reputation: 5286
There are a few things to think about when creating Regex expressions in postgresql. First, you need to escape backslashes. So instead of \
, you need \\
. Second, you can reference capturing groups by using \n to capture the nth group in parentheses. You can use the capturing group in your replace value to reference parts of the original string.
Putting all of this together, this is what you need:
regexp_replace('hour', '(\\d{4}-\\d{2}-\\d{2})-(\\d{2}:\\d{2}:\\d{2})', '\\1 \\2')
Upvotes: 4
Reputation: 658242
regexp_replace(hour, '(^\\d{4}-\\d{2}-\\d{2})-(\\d{2}:\\d{2}:\\d{2}$)', '\\1 \\2') AS a
regexp_replace(hour, '(^\\d{4}-\\d\\d-\\d\\d)-(\\d\\d:\\d\\d:\\d\\d)$', '\\1 \\2') AS b
regexp_replace(hour, '(^[\\d-]{10})-([\\d:]+)$', '\\1 \\2') AS c
left(hour,10) || ' ' || substring(hour FROM 12) AS e
regexp_replace(hour, '(^\d{4}-\d{2}-\d{2})-(\d{2}:\d{2}:\d{2}$)', '\1 \2') AS a
regexp_replace(hour, '(^\d{4}-\d\d-\d\d)-(\d\d:\d\d:\d\d)$', '\1 \2') AS b
regexp_replace(hour, '(^[\d-]{10})-([\d:]+)$', '\1 \2') AS c
reverse(regexp_replace(reverse(hour), '-', ' ')) AS d
left(hour,10) || ' ' || right(hour, -11) AS e
overlay(hour placing ' ' from 11) AS f
to_timestamp(hour, 'YYYY-MM-DD-HH24:MI:SS') AS ts
From "restrictive" to "cheap" in order of appearance. ts
is special.
That's like the currently accepted answer by @Zeki, completed with anchors at start and end with ^
and $
to make it even less ambiguous and potentially faster.
You want the special meaning of \d
as class shorthand for digits.
In Postgres, do not escape backslashes \
with \\
. That would be incorrect unless you are running with the long outdated, non-default setting standard_conforming_strings = off
.
Redshift is stuck at an old stage of development and does just that. Backslashes are interpreted unless escaped with another backslash.
\d\d
is shorter and cheaper than \d{2}
.
Simplify with a character classes: digits + hyphen: [\d-]
and digits + colon: [\d:]
.
Since regexp_replace()
without 4th parameter 'g'
only replaces the first match, you can reverse()
the string, replace the first hyphen and reverse()
back.
Doesn't work in Redshift, since it uses a simpler version of regexp_replace()
that always replaces all occurrences.
If the format is fixed as shown, just take the first 10 character, a blank and the rest of the string.
Redshift uses simpler versions of left()
and right()
that don't accept negative parameters, so I substituted with substring()
.
Or, simpler yet, just overlay() the 11th character with a blank.
Not implemented in Redshift.
Unlike the rest, to_timestamp()
returns a proper timestamp with time zone
type, not text
. You can assign the result to timestamp without time zone
just as well. Details.. By far the best option if you want to convert your string.
Not implemented in Redshift.
Upvotes: 3
Reputation: 67988
(\d{4}-\d{2}-\d{2})-(\d{2}:\d{2}:\d{2})
Try this.Replace by $1 $2
.See demo.
https://regex101.com/r/iY3eK8/13
Upvotes: 2