0

I need to convert a string to a date field. The field stores 30 characters. Dates, when present, are formatted as 'yyyymmdd' (20170202). In all cases, dates have 22 spaces after. I need to format this field as a date field like this: dd-mm-yyyy.

I've tried several formulas: TO_CHAR(PERSACTION.NEW_VALUE_02, 'dd-mm-yyyy') ,TO_CHAR(PERSACTION.NEW_VALUE_02, 'yyyymmdd'), trim(TO_CHAR(PERSACTION.NEW_VALUE_02, 'yyyymmdd')) with error message: invalid number format model. Your expertise is welcome and appreciated.

4
  • Don't understand that you say the field is date but holds 30 characters. Please include the table definition. Commented Feb 28, 2017 at 18:14
  • You want to convert string to date. Exact quote from your title and from your post. Now, Oracle has functions TO_CHAR and TO_DATE. If you want to convert to date, which of these two functions (again, their names are TO_CHAR and TO_DATE) do you think is more likely to be the right one? Commented Feb 28, 2017 at 18:40
  • The table is a String(30). And I agree, I wish we had control over how the data is stored in the table but sadly we don't. Commented Feb 28, 2017 at 18:42
  • 4
    On a different note, if you want to convert to date then there is no "format" - date fields don't have formats. The formats are only for strings, when you convert a string to a date (as you store data in the table in the proper data type, which is DATE) and when you convert a date back to a string, ONLY FOR REPORITING PURPOSES. Commented Feb 28, 2017 at 18:44

4 Answers 4

3
to_char(to_date( rtrim(new_value_02), 'yyyymmdd'), 'dd-mm-yyyy')

Should do the trick. rtrim removes spaces on right side of string. Then I convert it to date using the date format specified, and then convert it to a string again in the desired format.

Sign up to request clarification or add additional context in comments.

3 Comments

If the OP wants to convert to date, why is TO_CHAR needed at all?
This worked perfectly, I will keep this for future use too, thank you very much
@mathguy good point. I added this because he specifically mentions a date format as result. But a date in datatype Date has no format, it's just the representation of a specific date. Just leave the to_char out and you'll have a date.
2

Did tried to convert to date format and then to char again?

TO_CHAR(TO_DATE(PERSACTION.NEW_VALUE_02,'yyyymmdd'),'dd-mm-yyyy')

2 Comments

If the OP wants to convert to date, why is TO_CHAR needed at all?
Because it needs to be char. The value is stored in a text field not in a date field as Tania asked.
1

Please, please, please do not store DATEs and CHARACTER datatypes. This will only lead to issues that can be avoided when using the DATE datatype.

Comments

0

If you want to change the string 20170202 to another string and not actually a date (which would have no intrinsic formatted text representation), you could optionally use a regular expression to transform it, instead of converting to a date and back:

select regexp_replace('20170202     ', '^(\d{4})(\d{2})(\d{2}) +$', '\3-\2-\1')
from dual;

REGEXP_REPLACE(
---------------
02-02-2017     

Or you could use substr instead of regexp_substr, which may perform better even if you have to call it three times; using a CTE just to avoid repeating the value:

with t(str) as (
  select '20170202     ' from dual
)
select substr(str, 7, 2) ||'-'|| substr(str, 5, 2) ||'-'|| substr(str, 1, 4)
from t;

SUBSTR(STR
----------
02-02-2017

If you do convert to a date and back you would uncover any values which cannot be converted, as they will cause an exception to be thrown. That would imply you have bad data; which would have been avoided by using the right data type in the first place, of course. These will convert any old rubbish, with varying results depending on how far the strings stray from the pattern you expect - but including strings like '20170231' which represent an invalid date. And null value or strings of just spaces will be converted to odd things with the substr version, but you could filter those out.

You can see the kind of variation you would get with some sample data that doesn't match your expectations:

with t(str) as (
  select '20170202     ' from dual
  union all select '20170231     ' from dual
  union all select '2017020c     ' from dual
  union all select '2017020      ' from dual
  union all select '201702021    ' from dual
  union all select '             ' from dual
  union all select null from dual
)
select str,
  regexp_replace(str, '^(\d{4})(\d{2})(\d{2}) +$', '\3-\2-\1') as reg,
  substr(str, 7, 2) ||'-'|| substr(str, 5, 2) ||'-'|| substr(str, 1, 4) as sub
from t;

STR           REG           SUB          
------------- ------------- -------------
20170202      02-02-2017    02-02-2017   
20170231      31-02-2017    31-02-2017   
2017020c      2017020c      0c-02-2017   
2017020       2017020       0 -02-2017   
201702021     201702021     02-02-2017   
                              -  -       
                            --           

With the anchors and whitespace expectation, the regular expression doesn't modify anything that doesn't consist entirely of 8 numeric characters. But it can still form invalid 'dates'.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.