The current arrangement is:
SAP DSO: contains the data columns in the form of dd-mm-yyyy.
The BODS job fetches the data from the DSO and loads to the landing table.
The corresponding date column in Teradata is dd-mm-yy.
When the dates are loaded to teradata, year 2014 is converted to 1914.
There is no transformation involved. Direct mapping between the source and target.
This issue started happening only a few months back. Not sure what to check.
To show the correct year in your date, use the DateTime format dd-mm-rrrr.
When dates are stored in one century but refer to another century, dates can be shown with the wrong prefix. The rrrr year format works as so;
If the specified two-digit year is 00 to 49, then
If the last two digits of the current year are 00 to 49, then the
returned year has the same first two digits as the current year.
If the last two digits of the current year are 50 to 99, then the
first 2 digits of the returned year are 1 greater than the first 2
digits of the current year.
If the specified two-digit year is 50 to 99, then
If the last two digits of the current year are 00 to 49, then the
first 2 digits of the returned year are 1 less than the first 2 digits
of the current year.
If the last two digits of the current year are 50 to 99, then the
returned year has the same first two digits as the current year.
I came across a similar issue with BOXI 3.1 and Oracle.
After creating a number of tables with Date fields with the DateTime format as dd/mm/yyyy, and building a universe with this format in mind, I noticed on testing that some of the date results were displaying incorrectly e.g. 01/07/1993 was displaying as 01/07/2093. This was due to the data being loaded into the table having only 2 yy digits e.g. 01/07/93where as Oracle was expecting a DateTime format with 4 yyyy digits.
In turn, Oracle was forcing the year format into 4 digits but as the year was in the last century (20th) but stored in the 21st Century, the wrong century was prefixed onto the year.
To solve, I used the rrrr DateTime Format for the year. Full explaination from Oracle at this link, and further explaination can be found here.
When I recreated the table with the DateTime format as dd-mm-rrrr, the date displayed correctly.
I hope this helps.
DBSControl for CenturyBreak specifies which two-digit years are interpreted as 20th century and which are interpreted as 21st century. If your system has this configured as a non-zero value, which is the default, than this is quite possibly the reason you are seeing the behavior with your data.
CenturyBreak does not affect four digit years or dates input as numeric.
If CenturyBreak=10, strings such as '00/01/01' and '09/01/01' are interpreted as 2000 and 2009. A string inserted as '14/01/01' is interpreted as 1914.
Check with your DBA to determine if the CenturyBreak has been set to a non-zero value or explicitly convert your data inputs to numeric date values.
Related
I have 70.000 rows of data, including a date time column (YYYY-MM-DD HH24-MM-SS.).
I want to split this data into 3 separate columns; Hour, day and Week number.
The date time column name is 'REGISTRATIONDATE' from the table 'CONTRACTS'.
This is what I have so far for the day and hour columns:
SELECT substr(REGISTRATIONDATE, 0, 10) AS "Date",
substr(REGISTRATIONDATE, 11, 9) AS "Hour"
FROM CONTRACTS;
I have seen the options to get a week number for specific dates, this assignment concerns 70.000 dates so this is not an option.
You (the OP) still have to explain what week number to assign to the first few days in a year, until the first Monday of the year. Do you assign a week number for the prior calendar year? In a Comment I asked about January 1, 2017, as an example; that was a Sunday. The week from January 2 to January 8 of 2017 is "week 1" according to your definition; what week number do you assign to Sunday, January 1, 2017?
The straightforward calculation below assigns to it week number 0. Other than that, the computation is trivial.
Notes: To find the Monday of the week for any given date dt, we can use trunc(dt, 'iw'). iw stands for ISO Week, standard week which starts on Monday and ends on Sunday.
Then: To find the first Monday of the year, we can start with the date January 7 and ask for the Monday of the week in which January 7 falls. (I won't explain that one - it's easy logic and it has nothing to do with programming.)
To input a fixed date, the best way is with the date literal syntax: date '2017-01-07' for January 7. Please check the Oracle documentation for "date literals" if you are not familiar with it.
So: to find the week number for any date dt, compute
1 + ( trunc(dt, 'iw') - trunc(date '2017-01-07', 'iw') ) / 7
This formula finds the Monday of the ISO Week of dt and subtracts the first Monday of the year - using Oracle date arithmetic, where the difference between two dates is the number of days between them. So to find the number of weeks we divide by 7; and to have the first Monday be assigned the number 1, instead of 0, we need to add 1 to the result of dividing by 7.
The other issue you will have to address is to convert your strings into dates. The best solution would be to fix the data model itself (change the data type of the column so that it is DATE instead of VARCHAR2); then all the bits of data you need could be extracted more easily, you would make sure you don't have dates like '2017-02-29 12:30:00' in your data (currently, if you do, you will have a very hard time making any date calculations work), queries will be a lot faster, etc. Anyway, that's an entirely different issue so I'll leave it out of this discussion.
Assuming your REGISTRATIONDATE if formatted as 'MM/DD/YYYY'
the simples (and the faster ) query is based ond to to_char(to_date(REGISTRATIONDATE,'MM/DD/YYYY'),'WW')
(otherwise convert you column in a proper date and perform the conversio to week number)
SELECT substr(REGISTRATIONDATE, 0, 10) AS "Date",
substr(REGISTRATIONDATE, 11, 9) AS "Hour",
to_char(to_date(REGISTRATIONDATE,'MM/DD/YYYY'),'WW') as "Week"
FROM CONTRACTS;
This is messy, but it looks like it works:
to_char(
to_date(RegistrationDate,'YYYY-MM-DD HH24-MI-SS') +
to_number(to_char(trunc(to_date(RegistrationDate,'YYYY-MM-DD HH24-MI-SS'),'YEAR'),'D'))
- 2,
'WW')
On the outside you have the solution previous given by others but using the correct date format. In the middle there is an adjustment of a certain number of days to adjust for where the 1st Jan falls. The trunc part gets the first of Jan from the date, the 'D' gets the weekday of 1st Jan. Since 1 represents Sunday, we have to use -2 to get what we need.
EDIT: I may delete this answer later, but it looks to me that the one from #mathguy is the best. See also the comments on that answer for how to extend to a general solution.
But first you need to:
Decide what to do dates in Jan before the first Monday, and
Resolve the underlying problems in the date which prevent it being converted to dates.
On point 1, if assigning week 0 is not acceptable (you want week 52/53) it gets a bit more complicated, but we'll still be able to help.
As I see it, on point 2, either there is something systematically wrong (perhaps they are timestamps and include fractions of a second) or there are isolated cases of invalid data.
Either the length, or the format, or the specific values don't compute. The error message you got suggests that at least some of the data is "too long", and the code in my comment should help you locate that.
I'm looking for a way to convert an ISO date to Month and I also need to covert an ISO week to Month.
I need to do this in Excel and Access.
I found this formula for excel but when converting it to Access it does not work. Is there a simple way to accomplish this?
I found this Excel formula to convert ISO date to month (C2=date) and it works perfect:
=MONTH(DATE(YEAR(C2),MONTH(C2)+(WEEKDAY(C2,2)+(DAY(DATE(YEAR(C2),MONTH(C2)+1,0)))-(DAY(C2))<4),(((7-(WEEKDAY(C2,2)))+(DAY(C2)))>3)))
But when I modify it for an Access query it does not return the correct values:
Date_to_Month:MONTH(DATESERIAL(YEAR([WW_Index].[ISO_date]),MONTH([WW_Index].[ISO_date])+(WEEKDAY([WW_Index].[ISO_date],2)+(DAY(DATESERIAL(YEAR([WW_Index].[ISO_date]),MONTH([WW_Index].[ISO_date])+1,0)))-(DAY([WW_Index].[ISO_date]))<4),(((7-(WEEKDAY([WW_Index].[ISO_date],2)))+(DAY([WW_Index].[ISO_date])))>3)))
I also need to convert ISO week_year to Month. I found this formula but it does not work:
=MONTH(DATE(YEAR(C2),1,-2)-WEEKDAY(DATE(YEAR(C2),1,3))+D2*7)
Example: week 18, 2012 is the ISO week of Apr 30 through May 6, 2012. There is less that 4 April days in this week thus week 18, 2012 is in May.
Any help would be greatly appreciated.
I don't know access but you can do the first part (date to month) much more easily in excel with this formula
=MONTH(C2-WEEKDAY(C2-1)+4)
That should be easier to convert for access......
For the second part you are finding the Monday of the relevant week, hence you get the wrong month in some cases, the Thursday of the week (midpoint) should always be within the correct month so you can just add 3 to get that (-2 becomes 1), i.e.
=MONTH(DATE(YEAR(C2),1,1)-WEEKDAY(DATE(YEAR(C2),1,3))+D2*7)
I assume C2 is a date within the relevant year and D2 is the ISO week number
but probably better to have C2 containing the year, e.g. just 2013 and then you can use
=MONTH(DATE(C2,1,1)-WEEKDAY(DATE(C2,1,3))+D2*7)
I am trying to convert column with GMT hour to the specified time zones from the user.
I get an error when VBA attempts to subtract 18000 secs (GMT-5) from 01:00.
Selected_GMT = -18000
CellValue = "1/0/00 01:00"
New_Time = DateAdd("s", Selected_GMT,CellValue)
Is this error happening because VBA is unable to determine the hours before 00:00?
I have figured out the seconds for Selected_GMT, how can I use that to determine New_Time?
As ooo noted in a comment above, 1/0/00 is an invalid date code. However even if that was a typo in your question, the fact that the date uses a 2 digit year code begs the question "WHICH year 00?" Apologies if you already know this, but below I've extracted a recap of how Excel dates work from something that I've written elsewhere. The relevant part is "Day Zero And Before In Excel"; if the "00" actually represents *19*00 in the cell (as it will if you've just punched in "01:00 as the cell entry), you're going to run into problems subtracting from that. In which case, perhaps explicitly enter the date and time (perhaps using the current date) but hide the date component using formatting):
Excel uses a "date serial" system in which any date that you use in
calculations is represented as a positive integer value. That integer
value is calculated from an arbitrary starting date. Adding whole
numbers to a specific serial date moves you forward through the
calendar a day at a time, and subtracting whole numbers moves you
backwards... as long as you don't go past the starting date of the
serial number system and end up with a negative value. Times are
represented as fractions of a day; 0.25 for 6am, 0.5 for noon, 0.75
for 6pm and so on.
Excel Dates
In the case of Excel for Windows, the starting date is 1 January 1900. That is, if you enter the value 1 into a cell in Excel
and format it as a date, you'll see the value as 1 January 1900. 2
will be the 2nd of January 1900, 3 the 3rd of January, and so on. 367
represents 1 January 1901 because Excel treats 1900 as having been a
leap year with 366 days. In other words, every full day that passes
adds 1 to the serial date.
It's important to remember that the above relates to Excel only, and
not to Access, SQL Server or other database products (or Visual Basic,
for that matter). In Access, for example, the range of valid dates is
1 January 100 to 31 December 9999, the same range that can be stored
in a VB or VBA variable with a Date data type.
Excel And The Macintosh
Macintosh systems use a start date of 1 January 1904, neatly bypassing the 1900 leap year issue. However that
does mean that there's a 4 year discrepancy between the serial date
values in a workbook created in Excel for Windows, and one created in
Excel for the Mac. Fortunately under Tools -> Options-> Calculation
(on pre-2007 versions of Excel) you'll find a workbook option called
1904 Date System. If that's checked, Excel knows that the workbook
came from a Macintosh and will adjust its date calculations
accordingly.
Excel Times
As noted in the introduction, times are calculated as a
fraction of a day. For example 1.5 represents noon on 2 January 1900.
1.75 represents 6pm on 2 January 1900.
(Snipped a bit about the leap year bug in 1900)
From 1 March 1900 onward Excel's dates are correct, but if you format
the number 1 using the format dddd, mmmm dd, yyyy you'll get the
result Sunday, 1 January 1900. That is incorrect; 1 January 1900 was a
Monday, not a Sunday. This day of week error continues until you reach
1 March, which is the first truly correct date in the Excel calendar.
Day Zero And Before In Excel
If you use the value zero and display it
in date format you'll get the nonsense date Saturday 0 January 1900.
If you try to format a negative value as a date, you'll just get a
cell full of hash marks. Similarly if you try to obtain a date serial
number using Excel functions like DateValue, you can only do so for
dates on or after 1 January 1900. An attempt to specify an earlier
date will result in an error.
The 1904 (Macintosh) system starts from zero. (1 January 1904 has a
value of 0, not 1. Excel's on-line help describes the Mac system as
starting from January 2, but that's probably easier than explaining to
users why a serial date value of 0 works on the Mac but not Excel.)
Negative numbers won't generate an error, but the number will be
treated as absolute. That is, both 1 and -1 will be treated as 2
January 1904.
I found below statement regarding "date" column type:
"date" stores only the date component
without the time component, ranging
from 1st January 0001 to 31st December
9999, with accuracy of 1 day
I am not able to understand what is meaning of accuracy here?
I found this statement on:
http://www.sqlservercentral.com/articles/News/3253/
day because it's "date"
Read The ultimate guide to the datetime datatypes by Tibor Karaszi
It means that the minimum difference from date to date is a single day, nothing less.
In other words, you can't store hours in a date column.
Or, that the data is accurate to within a day.
See date on MSDN:
Range - 0001-01-01 through 9999-12-31. January 1, 1 A.D. through December 31, 9999 A.D.
Accuracy - One day
The date type stores the value internally as an integer, meaning the number of days since 0001-01-01. The value 0001-01-03 for example would be stored internally as 2.
The term "accuracy" is probably used here because it's used to express the resolution of other date/time types. The resolution for the date type is simply one day, just as you would expect. The accuracy (resolution) for the datetime type for example is 3.33 milliseconds.
I agree the use of "accuracy" is poor wording.
Personally, I would employ the phrase, "its smallest time granule is one day."
Accuracy?
It does what it says. It stores a date, not time...
From date (Transact-SQL)
Element ranges
YYYY is four digits from 0001 to 9999
that represent a year.
MM is two digits from 01 to 12 that
represent a month in the specified
year.
DD is two digits from 01 to 31,
depending on the month, that represent
a day of the specified month.
where as
from datetime (Transact-SQL)
Element ranges
YYYY is four digits from 1753 through
9999 that represent a year.
MM is two digits, ranging from 01 to
12, that represent a month in the
specified year.
DD is two digits, ranging from 01 to
31 depending on the month, that
represent a day of the specified
month.
hh is two digits, ranging from 00 to
23, that represent the hour.
mm is two digits, ranging from 00 to
59, that represent the minute.
ss is two digits, ranging from 00 to
59, that represent the second.
n* is zero to three digits, ranging
from 0 to 999, that represent the
fractional seconds.
Example:
select ename from emp where hiredate = todate('01/05/81','dd/mm/yy')
and
select ename from emp where hiredate = todate('01/05/81','dd/mm/rr')
return different results
http://oracle.ittoolbox.com/groups/technical-functional/oracle-dev-l/difference-between-yyyy-and-rrrr-format-519525
YY allows you to retrieve just two digits of a year, for example, the 99 in
1999. The other digits (19) are automatically assigned to the current
century. RR converts two-digit years into four-digit years by rounding.
50-99 are stored as 1950-1999, and dates ending in 00-49 are stored as
2000-2049. RRRR accepts a four-digit input (although not required), and
converts two-digit dates as RR does. YYYY accepts 4-digit inputs butdoesn't
do any date converting
Essentially, your first example will assume that 81 is 2081 whereas the RR one assumes 1981. So the first example should not return any rows as you most likely did not hire any guys after May 1 2081 yet :-)
y2k compatibility. rr assumes 01 to be 2001, yy assumes 01 to be 1901
see: http://www.oradev.com/oracle_date_format.jsp
edit: damn! michael "quickfingers" stum beat me to it!
/mp
#Michael Stum
My last Oracle experience is a bit long ago
uhm, was it, before 2000? :p
...
Will yy always assume 19xx?
according to your source, we get the following scenarios:
USING
ENTERED
STORED
SELECT of date column
YY
22-FEB-01
22-FEB-1901
22-FEB-01
YYYY
22-FEB-01
22-FEB-0001
22-FEB-0001
RR
22-FEB-01
22-FEB-2001
22-FEB-01
RRRR
22-FEB-01
22-FEB-2001
22-FEB-2001
/mp
RR displays four digits as 1999 or 2015(if it is <49 then it will consider 20th century)
About RR or RRRR
When we are inserting the dates with 2 digits years (i.e. 09/oct/15)
then Oracle may changes the centuries automatically hence the
solution is 4 digit dates. But 4 digit version is introduced in
some recent versions, therefore the solutions for this problem
in earlier versions was RR or RRRR. But note that it only works
with the TO_DATE() function but not with the TO_CHAR() function.
Whenever inserts/updates are conducted upon dates we should always clarify current date running in the clock in association with the date translation since Oracle conducts every date translation by contacting the server.
In order to keep the consistencies among the centuries, it is always better to execute the date translation with 4 digit years.
About YY or YYYY
It accepts the dates but doesn't has functionality to automatically change it.
This Image shows behaviour when inserting date with two digit (i.e.
09/oct/15)
RR stands for after 1990 and yy assumes 90 as 2090....as we are in the current yr,...