Convert a BC date to an AD - sql

I have dates, which are prior to year 0. I need to convert them to an AD date and add 1 year more. For example I have BC 16.2.2011 and want AD 16.2.2012.
We have a 3rd side Java application, in which sometimes an error occurs; it saves the date incorrectly. In example above it should save 16.2.2012 but instead, in the DB, is -16.2.2011 (it is one "year smaller" because Oracle has no year zero - this is important).
Converting these dates is easy, but the problem is that when a saved date should be 29.2.2012 because there is no -29.2.2011. Instead of this date it saves -1.3.2011, which I can't convert easily.
Is there any way to convert the date correctly? Like get seconds from start year right from dump data in the database?

Tell us if it is something wrong with:
select to_date(to_char(your_bc_date_here,'dd.mm.YYYY'), 'dd.mm.YYYY') + 1 from dual;
This is a wrong cast because it does not considers year may be negative(correct would be syyyy)
I've tested with: your_bc_date = to_date('BC 28.2.2011', 'BC dd.mm.yyyy')

Related

SQL Server Not Casting String YYYYMMdd to Date

I have a query that was working fine before a server migration and now is not working. I'm trying to convert all dates to a specific month and year, but I keep getting this error:
Conversion failed when converting date and/or time from character string.
Looking into the data, there are no null values in InputDate, which is a date data type column. When I run the Concat() function everything is formatted as 'YYYYMMdd', yet both CAST and CONVERT fail with the same error.
Is there an issue with my query that I'm not seeing?
SELECT RandoSTUFF,
DATEADD(day,2,CAST(CONCAT('2023','02',FORMAT(InputDate,'dd')) AS date)) AS MovedDate
FROM a_table_
I expect the issue is you have date values near the end of their months, and you're trying to compose the equivalent values for February, which is shorter.
So if you have an InputDate value of, say, 2022-12-31 and run the code in the question, it will extract the 31 and concat it with the other values, and you'll end up trying to do this:
CAST('20230231' as Date)
Of course, there is no such date.
As it is, it's not clear whether you want such an input to map to February 28 or March 3. To fix this, you'll need to rethink the problem so you only try to map to valid dates, and ensure the final result is more clearly defined. This is one of the many reasons it's almost always better to use Date/time functions instead of composing dates from strings.

Error when grabbing rows within current month

I'm trying to grab all rows that fall into the current month. For now, I'm just hard coding the month since I can't even get that to work properly.
I did the following to convert my dates to the format "DD-MON-YYYY'
SELECT "MOLECULE_NAME", to_date("FLASK_START_DATE", 'MM/DD/YYYY')
FROM EXCEL_SCHEDULE_IMPORT
Which gives me the correct date output I want. But now, when I try to grab all the dates that fall into this current month with the following code, it's a no go. Getting the error "invalid number".
SELECT "MOLECULE_NAME", to_date("FLASK_START_DATE", 'MM/DD/YYYY')
FROM EXCEL_SCHEDULE_IMPORT
WHERE to_char("FLASK_START_DATE",'Mon-YYYY')='JUN-2017';
Any help would be appreciated. I want to end up grabbing all values from a current month based off the system clock. So if you can do that... That would be cool.
EDIT: Turns out some of the dates in the date column turn out to have incorrect data, such as "Molecule" or "Sequence". So words instead of a date. Is there any way to ignore those values?
If you want data from the current month, why not just do:
WHERE "FLASK_START_DATE" like TO_CHAR(sysdate, 'MM') || '/%/' + TO_CHAR(sydate, 'YYYY')
Or:
WHERE "FLASK_START_DATE" like '06/%/2017'
Why go back and forth on string and date conversions? Also, you should be storing date in the proper data type -- called DATE.

Converting data with to_date function and combination of substrings

some of my teammates messed up date format which is now in YYYY-DD-MM format 2013-24-09 in my table on Oracle database. I want to convert it into date format and try following code:
TO_DATE((SUBSTR(BEGINNING_DATE, 1, 4)||'-'||substr(BEGINNING_DATE, 9,2)||'-'||substr(BEGINNING_DATE,6, 2)), 'YYYY-MM-DD')
Still an error appears:
ERROR [HY000] ERROR: to_timestamp(): bad value 31 for day of the month
When I hower select seprate substrings into columns everything looks like below and I believe it is ok.
YYYY MM DD
2013 12 31
I wonder where do I make mistake. Can you help me?
If the value is stored in the database as a string, and you just want a date out of it, TO_DATE(BEGINNING_DATE, 'YYYY-DD-MM') should suffice. You could then convert it back with TO_CHAR (with the correct format) if you're trying to fix the records in the database.
As for your particular error, if they are all stored as strings, you might want to check what value it is failing on, and make sure that one in particular is valid (e.g., it isn't '2013-02-31' or something).

Fetching the records which are having all time stamp columns

I am trying to fetch the records which are having all time stamp columns.
I am using the following query to fetch the products that are created between the final date and (final date - 30) days, i.e products created during the last 30 days that fall in the 'final date' range.
I have products that are created on 30-OCT-2014. For the same products, the initiated date is 12-NOV-2014. However they are not being fetched when I using the below query.
SELECT A.ROW_ID,
A.PROD_NAME
FROM PROD A,
PROD_REL B
WHERE A.ROW_ID = B.PAR_ROW_ID
AND TO_DATE(A.CREATED_DT,'YYYY-MM-DD') BETWEEN (TO_DATE(B.FINAL_DATE,'YYYY-MM-DD') - 30)
AND (TO_DATE(B.FINAL_DATE,'YYYY-MM-DD'));
So, could you please let me know if I am missing something?
Here is a link to a SQLFiddle that demonstrates the problem.
… or just fix your format string TO_DATE(A.CREATED,'DD-MON-YYYY')
SQL Fiddle
Storing dates as DATE, is , of course, always a good starting point.
Since your data types are all dates, there is no need to use to_date. It's harmful, in fact, since to_date doesn't take a date as a parameter. Oracle has to do an implicit conversion from a date to a string, using your session's NLS_DATE_FORMAT which gets passed in to to_date and converted back to a date using the explicit format mask you specified. If the two conversions aren't using the same format mask, bad things happen.
Your WHERE clause just needs to be
AND a.created_dt BETWEEN b.final_date - 30
AND b.final_date
If I make that change, your SQLFiddle returns two rows

Unknown SQL coding issue in Oracle SQL Developer

I'm writing an SQL statment that is supposed to do a count based on a date range. But, for some reason no data is being returned. Before I try and filter the count with my date range, everything works fine. Here is that code.
SELECT
CR.GCR_RFP_ID
,S.RFP_RECEIVED_DT
,CR.GCR_RECEIVED_DT
,CT.GCT_LOB_IND
FROM ADM.GROUP_CHANGE_TASK_FACT CT
JOIN ADM.B_GROUP_CHANGE_REQUEST_DIM CR
ON CR.GROUP_CHANGE_REQUEST_KEY = CT.GROUP_CHANGE_REQUEST_KEY
JOIN ADM.B_RFP_WC_COVERAGE_DIM S
ON S. RFP_ID = CR.GCR_RFP_ID
WHERE CT.GCT_LOB_IND = 'WC'
AND CR.GCR_CHANGE_TYPE_ID IN ('10','20','30','50','60','70','80','90','100','110',
'120','130','140', '150','160','170','180','190','200',
'210','220','230','240','260','270','280','300','310',
'320','330','340','350','360','370','371','372')
AND S.RFP_AUDIT_IND = 'N'
AND S.RFP_TYPE_IND = 'A'
The date field I'm using is called CR.GCR_RECIEVED_DT. This is a new field a in the db and all the records are 01-JAN-00. But I'm still doing the count just to make sure I can grab the data. Now, I added this line:
AND CR.GCR_RECEIVED_DT LIKE '01-JAN-00'
just as a random test thing. I know all the dates are the same. And it works fine, no issues. So I remove that line and replace it with this:
AND CR.GCR_RECEIVED_DT BETWEEN '31-DEC-99' AND '02-JAN-00'
I used this small range to keep it simple. But even though 01-JAN-00 deffinetly falls between those two dates, no data is returned. I have no idea why this is happening. I even tried this line to:
AND CR.GCR_RECEIVED_DT = '01-JAN-00'
and I still don't get data returned. It only seems to work with LIKE. I have checked and the field is a date type. Any help wold be much appreciated.
If your NLS_DATE_FORMAT is set to DD-MON-YY then the apparent discrepancy between the first two results can be explained.
When you use LIKE it implicitly converts the date value on the left-hand side to a string for the comparison, using the default format model, and then compares that to the fixed string; and '01-JAN-00' is like '01-JAN-00'. You're effectively doing:
AND TO_CHAR(CR.GCR_RECEIVED_DT, 'DD-MON-YY') LIKE '01-JAN-00'
Using LIKE to compare dates doesn't really make any sense though. When you use BETWEEN, though, the left-hand side is being left as a date, so you're effectively doing:
AND CR.GCR_RECEIVED_DT BETWEEN TO_DATE('31-DEC-99', 'DD-MON-YY')
AND TO_DATE('02-JAN-00', 'DD-MON-YY')
... and TO_DATE('31-DEC-99', 'DD-MON-YY') is December 31st 2099, not 1999. BETWEEN only works when the first value is lower than the second (from the docs, 'If expr3 < expr2, then the interval is empty'). So you're looking for values bwteen 2099 and 2000, and that will always be empty. If your date model was DD-MON-RR, from the NLS parameter or explicitly via TO_DATE, then it would be looking for values between 1999 and 2000, and would find your records.
Your third result is a little more speculative but suggests that the values in your GCR_RECEIVED_DT field have a time component, or are not in the century you think. This is similar to the LIKE version, except this time the fixed string is being converted to a date, rather than the date being converted to a string; effectively:
AND CR.GCR_RECEIVED_DT = TO_DATE('01-JAN-00', 'DD-MON-YY')
If they were at midnight on 2000-01-01 this would work. Because it doesn't that suggests they are either some time after midnight, or maybe more likely - since you're using a 'magic' date in your existing records - they are another date entirely, quite possibly 1900-01-01.
Here are SQL Fiddles for just past midnight and 1900.
If the field will eventually have a time component for new records you might want to structure the condition like this, and use date literals to be a bit clearer (IMO):
AND CR.GCR_RECEIVED_DT >= DATE '2000-01-01'
AND CR.GCR_RECEIVED_DT < DATE '2000-01-02'
That will find any records at any time on 2000-01-01, and can use an index on that column if one is available. BETWEEN is inclusive, so using BETWEEN DATE '2000-01-01' AND '2000-01-02' would include any records that are exactly at midnight on the later date, which you probably don't want.
Whatever you end up doing, avoid relying on implicit conversions using NLS_DATE_FORMAT as one day it might not be set to what you expect, causing potentially data-corrupting or hard to find bugs; and specify the full four-digit year in the model if you can to avoid ambiguity.
try something like this:
WHERE TRUNC(CR.GCR_RECEIVED_DT) = TO_DATE('01-JAN-00','DD-Mon-YY')
TRUNC without parameter removes hours, minutes and seconds from a DATE.