Discussion:
DATEPART function
(too old to reply)
VP1695
2004-07-09 12:33:36 UTC
Permalink
I just wanted to warn those of you who use the DATEPART function.
As many of you know, this function extracts the date from a SAS
datetime value. However, if you use DATEPART on the date (not
datetime) variable, the value of the function will become 0 which corresponds
to 01JAN1960
in SAS. Why would anybody want to use this function on the date? Well, I'll
give you a scenario. Let's say you extract data from Oracle using PROC SQL.
For some reason, SAS treats Oracle dates as datetime variables, and if you
want dates you may decide to use the DATEPART function in your SAS code.
Now, say, at some later point your database, data warehouse,... migrates to
another platform, say, Teradata. You are unaware that SAS reads Teradata
dates as dates and are using the same SAS code with the DATEPART functions
in it. It would be nice if SAS warned you that the argument of the DATEPART
function is invalid, but SAS doesn't give either an error message or at
least a warning and you are getting 01JAN1960 all over without even knowing
it.

Vadim Pliner
Chang Y. Chung
2004-07-09 15:25:04 UTC
Permalink
Post by VP1695
I just wanted to warn those of you who use the DATEPART function.
As many of you know, this function extracts the date from a SAS
datetime value. However, if you use DATEPART on the date (not
datetime) variable, the value of the function will become 0 which
corresponds
Post by VP1695
to 01JAN1960
in SAS. Why would anybody want to use this function on the date? Well,
I'll
Post by VP1695
give you a scenario. Let's say you extract data from Oracle using PROC
SQL.
Post by VP1695
For some reason, SAS treats Oracle dates as datetime variables, and if you
want dates you may decide to use the DATEPART function in your SAS code.
Now, say, at some later point your database, data warehouse,... migrates
to
Post by VP1695
another platform, say, Teradata. You are unaware that SAS reads Teradata
dates as dates and are using the same SAS code with the DATEPART functions
in it. It would be nice if SAS warned you that the argument of the
DATEPART
Post by VP1695
function is invalid, but SAS doesn't give either an error message or at
least a warning and you are getting 01JAN1960 all over without even
knowing
Post by VP1695
it.
Hi, Vadim,

I can understand the pain when you must have felt when you discovered that
the migrated data are incorrect.

Transferring (or migrating) data from one system to another, however, are
inherently difficult, in my opinion, because it requires the user to be
familiar with both the systems that are involved, plus whatever the
software tool or standard that are used in the process. This also means
that as long as different systems are involved, there are no reasons to
assume that the transfer code you wrote would work the same way as it did
before with a different system.

The best kind of transfer software tools, IMHO, let you specify, for each
var, the exact data types to be used on both input and output sides; it
should also let you spell out on which side the data type conversion
should occur and in which fashion. I am quite pleased with some of the
sas/access products in this regard.

The worst kind is the ones that try to be "smart" and hide all the details
from the user or, worse, do not allow such detailed user control over the
transfer process. Alas, it seems to me that the latter, rather then the
former, is the more popular kind.

Regarding the sas's datepart function, you may benefit from reminding
yourself that sas has only two different data types: numeric and
character. There are no date types. As such, the input to the datepart
function is simply a numeric type variable. Thus it is simply impossible
for sas to "detact" or "warn" user about the possible abuses like you
mention.

Hope this helps and good luck with your data migration in the future.

Cheers,
Chang
VP1695
2004-07-10 01:19:43 UTC
Permalink
Hi Chang,

I do remember that SAS has only two different data types: numeric and
character and there are no date types in SAS. However, I don't understand why
"it is simply impossible for sas to warn" about a potential misuse of the
DATEPART function. You are right, all date and datetime variables are numeric,
but their formats are different. Why couldn't SAS tell a date format from a
datetime one? Even if it was impossible, is it logical that the DATEPART of any
date (numeric variable formatted as a date) is 0 i.e. '01JAN1960'?

Vadim
Post by VP1695
Post by VP1695
I just wanted to warn those of you who use the DATEPART function.
As many of you know, this function extracts the date from a SAS
datetime value. However, if you use DATEPART on the date (not
datetime) variable, the value of the function will become 0 which
corresponds
Post by VP1695
to 01JAN1960
in SAS. Why would anybody want to use this function on the date? Well,
I'll
Post by VP1695
give you a scenario. Let's say you extract data from Oracle using PROC
SQL.
Post by VP1695
For some reason, SAS treats Oracle dates as datetime variables, and if you
want dates you may decide to use the DATEPART function in your SAS code.
Now, say, at some later point your database, data warehouse,... migrates
to
Post by VP1695
another platform, say, Teradata. You are unaware that SAS reads Teradata
dates as dates and are using the same SAS code with the DATEPART functions
in it. It would be nice if SAS warned you that the argument of the
DATEPART
Post by VP1695
function is invalid, but SAS doesn't give either an error message or at
least a warning and you are getting 01JAN1960 all over without even
knowing
Post by VP1695
it.
Vadim
Hi, Vadim,
I can understand the pain when you must have felt when you discovered that
the migrated data are incorrect.
Transferring (or migrating) data from one system to another, however, are
inherently difficult, in my opinion, because it requires the user to be
familiar with both the systems that are involved, plus whatever the
software tool or standard that are used in the process. This also means
that as long as different systems are involved, there are no reasons to
assume that the transfer code you wrote would work the same way as it did
before with a different system.
The best kind of transfer software tools, IMHO, let you specify, for each
var, the exact data types to be used on both input and output sides; it
should also let you spell out on which side the data type conversion
should occur and in which fashion. I am quite pleased with some of the
sas/access products in this regard.
The worst kind is the ones that try to be "smart" and hide all the details
from the user or, worse, do not allow such detailed user control over the
transfer process. Alas, it seems to me that the latter, rather then the
former, is the more popular kind.
Regarding the sas's datepart function, you may benefit from reminding
yourself that sas has only two different data types: numeric and
character. There are no date types. As such, the input to the datepart
function is simply a numeric type variable. Thus it is simply impossible
for sas to "detact" or "warn" user about the possible abuses like you
mention.
Hope this helps and good luck with your data migration in the future.
Cheers,
Chang
Terjeson, Mark
2004-07-09 16:20:31 UTC
Permalink
Hi Vadim,

Ahhhh, take heart, comfort may be achieved!

If you will indulge for a moment while I try to
bring newcomers to SAS up to speed I will provide
a very possible solution for to make your code
platform and date/datetime independent (i.e. generic).
Of course if your DATEs are dates-of-birth this won't
work, unless your population is a younger one, but if
your data is DATEs larger than 1/3/1960 this could
prove helpful, see end of message below. At least it
will give you kick start on how you could develop
something that might fit your needs. And who knows,
if your data is DOB with dates prior to 1960 you may
still yet find a convoluted scheme that might do
something similar.

The DATE and DATETIME and TIME stuff is not so
ominous, portentous, prodigious, inauspicious,
needing an augur to portend, prognosticate, or
presage.

The SAS date is merely a numeric number signifying
the number of "days" since January 1st, 1960. The
SAS time is the number of "seconds" since midnight.
The SAS datetime is the number of "seconds" since
January 1st, 1960.

Thus a numeric value of 0 (zero) for TIME is
midnight.

data _null_;
x = 0;
format x timeampm.;
put _all_;
run; * x=12:00:00 AM ;

For folks new to SAS the variable x contains
the value 0. The FORMAT statement just tells
SAS to not change the value of x but just to
redisplay the cosmetics to something else at
the time it gets displayed or printed out.
The numeric value of x remains unchanged.

Also, a numeric value of 0 (zero) for DATE is
January 1st, 1960.

data _null_;
x = 0;
format x mmddyy10.;
put _all_;
run; * x=01/01/1960 ;


As well as, a numeric value of 0 (zero) for
DATETIME is midnight January 1st, 1960.

data _null_;
x = 0;
format x datetime18.;
put _all_;
run; * x=01JAN1960:00:00:00 ;

To get a better understanding by just changing
the value 0 to something larger, say 16261.

data _null_;
x = 16261;
format x mmddyy10.;
put _all_;
run; * x=07/09/2004 ;

For those new to SAS, the question may be how
does the magic work to *know* what todays date is?
(the number of days since 1/1/1960 until today)

We ourselves can do the arithmetic as well to
compute and/or convert between each of these
units of measure.

You could use arithmetic and tally up the number
of years (adjusting for leap years and leap
centuries) then months and days until you came
up with the number of days since 1/1/1960, or
we can use the DATE() function built into SAS
that will return the integer value 16261 for
today. (that's the quick way) (see, no magic)

data _null_;
x = date();
format x mmddyy10.;
y = x;
put _all_;
run; * x=07/09/2004 y=16261 days since 1/1/1960 ;

In the same vein, the number of seconds (DATETIME)
for this morning, say 7:28AM, would be 1404977321.1.
(again, I'll cheat and do it the easy way using
the built in function to fetch it) You can compute
whole numbers (i.e. whole number of seconds) but
since all numeric variables in SAS while your datastep
or proc is running are 8 byte numbers which can hold
floating point values with a mantissa. (in other words,
can store fractions of seconds as well)

data _null_;
x = datetime();
format x datetime21.;
y = x; * get value of x and leave as unformatted number ;
put _all_;
run; * x=09JUL2004:07:28:41 y=1404977321.1 seconds since 1/1/1960 ;

You can see that you can manually initiate these values
by hand instead. (no magic yet)

data _null_;
x = 1404977321.1;
format x datetime21.;
put _all_;
run; * x=09JUL2004:07:28:41 ;

or to show more fraction digits

data _null_;
x = 1404977321.1;
format x datetime22.4;
put _all_;
run; * x=09JUL2004:07:28:41.1000 ;

Fetching current TIME also has a built in function.

data _null_;
x = time();
format x timeampm.;
y = x; * get value of x and leave as unformatted number ;
put _all_;
run;* x=7:28:41 AM y=26921 seconds since midnight ;

Okay, we've seen two methods so far, 1) hardcoding a number
manually by hand into a variable, and 2) fetching the current
values via the built in function calls.

Someone may now say running the datastep with the TIME()
function is obviously going to keep returning different
values each time you run the code. Yep, same for DATE() and
DATETIME(), you may keep getting different values relative
to grabbing the now-ever-changing-current values. So a
third variation so that we can actually hardcode or get a
value for some day or time back in the past (or future) is
provided by SAS in the syntax form of specifying a string
literal with a suffix modifier letting SAS know how to do
the arithmetic to convert to the appropriate units of measure.
For example, to keep fetching the exact number of seconds
since midnight for 7:28:41 AM over and over, the string
literal (sometimes known in the SAS world of documentation
as character constants) can be specified in more familiar
representation that is more meaningful to us, but yet the
SAS program immediate converts it to the desired number
value, such as '07:28:41't would be internally converted
to 26921 for the number of seconds since midnight.

data _null_;
x = '07:28:41't; * t = convert string to TIME value ;
format x timeampm.;
y = x; * get value of x and leave as unformatted number ;
put _all_;
run; * x=7:28:41 AM y=26921 seconds since midnight ;

So indeed you can get a constant value over and over.

The same can be done, not only for TIME, for DATE and DATETIME
values as well. Remember all three of these are just a number
with three different units of measure and starting point.

data _null_;
x = '9JUL2004'd; * d = convert to DATE value ;
format x mmddyy10.;
y = x; * get value of x and leave as unformatted number ;
put _all_;
run; * x=07/09/2004 y=16261 days since 1/1/1960 ;

and for DATETIME.

data _null_;
x = '09JUL04:07:28:41.1000'dt; * d = convert to DATETIME value ;
format x datetime18.;
y = x; * get value of x and leave as unformatted number ;
put _all_;
run; * x=09JUL04:07:28:41 y=1404977321.1 seconds since 1/1/1960 ;

The forth method of handling dates and times is to convert
between them. We can use built in functions such as DATEPART()
and TIMEPART() to get just those portions.

data _null_;
x = '09JUL04:07:28:41.1000'dt; * d = convert to DATETIME value ;
format x datetime18.;
y = x; * get value of x and leave as unformatted number ;
a = datepart(x);
format a mmddyy10.;
b = a; * get value of a and leave as unformatted number ;
put _all_;
run; * x=09JUL04:07:28:41 y=1404977321.1 a=07/09/2004 b=16261 ;

the above showing how to grab the date part. below how to get the
time part.

data _null_;
x = '09JUL04:07:28:41.1000'dt; * d = convert to DATETIME value ;
format x datetime18.;
y = x; * get value of x and leave as unformatted number ;
a = timepart(x);
format a timeampm.;
b = a; * get value of a and leave as unformatted number ;
put _all_;
run; x=09JUL04:07:28:41 y=1404977321.1 a=7:28:41 AM b=26921.1 ;

However, if we remember the definition of the three units of
measure, we can easily perform the same arithmetic that these
conversion routines perform (so still no magic). for date

data _null_;
x = '09JUL04:07:28:41.1000'dt; * d = convert to DATETIME value ;
format x datetime18.;
y = x; * get value of x and leave as unformatted number ;

NumberOfSecondsInADay = ((24 * 60) * 60);
a = x / NumberOfSecondsInADay; * same as a = datepart(x);

format a mmddyy10.;
b = a; * get value of a and leave as unformatted number ;
put _all_;
run; * x=09JUL04:07:28:41 y=1404977321.1 a=07/09/2004 b=16261 ;

and for time

data _null_;
x = '09JUL04:07:28:41.1000'dt; * d = convert to DATETIME value ;
format x datetime18.;
y = x; * get value of x and leave as unformatted number ;

NumberOfSecondsInADay = ((24 * 60) * 60);
a = mod(x,NumberOfSecondsInADay); * same as a = timepart(x);
* instead of the mod() function to get the leftover seconds
within a whole day you could also manually compute the
days for the date and multiply by number of seconds in a
day and then subtract that from x to get the leftover
seconds less than one day which is the TIME part. ;

format a timeampm.;
b = a; * get value of a and leave as unformatted number ;
put _all_;
run; * x=09JUL04:07:28:41 y=1404977321.1 a=7:28:41 AM b=26921.1 ;


Now being comfortable with how date and time values work and
that you can convert, compute, adjust them arithmetically
yourself such as add a day to a DATE, since a DATE is number
of days, merely add 1. If you wanted to add an minute to TIME
then just add 60, since the TIME unit of measure is in seconds.
Adding an hour would just be adding (60*60), i.e. 60 seconds
times 60 minutes would equal and hour, and (60*60)*24 would
be equal to a day in seconds.


Now back to your dilema. A possible safe platform and DATE
and DATETIME independent scheme of logic might be that you
could determine that you would never have any DATEs in your
data that occur in the next 500 years.

data _null_;
x = '1JAN2500'd; * d = convert to DATE value ;
format x mmddyy10.;
y = x; * get value of x and leave as unformatted number ;
put _all_;
run; * x=01/01/2500 y=197232 ;

and if we check the 197232 converted into DATETIME seconds
we see that it represents

data _null_;
x = 197232;
format x datetime22.;
y = x; * get value of x and leave as unformatted number ;
put _all_;
run; * x=03JAN1960:06:47:12 y=197232 ;

So *IF* the DATEs in your data were not DOBs, or at least
DOBs greater than January 3rd of 1960, then you could use
generic logic for both DATE or DATETIME platform conversions
with something like checking the magnitude of the number
value to interpret if the incoming value is in a DATE unit
of measure or in a SECONDS unit of measure:

* convert from DATETIME units if needed ;
if mydate > 197232 then mydate = datepart(mydate);
* else leave mydate in DATE units ;

Of course if you needed Jan 2nd and 3rd of 1960, and you can
deal with only 100 years of cushion you could use a smaller
number:

data _null_;
x = '1JAN2100'd; * d = convert to DATE value ;
format x mmddyy10.;
y = x; * get value of x and leave as unformatted number ;
put _all_;
run; * x=01/01/2100 y=51135 ;

data _null_;
x = 51135;
format x datetime22.;
y = x; * get value of x and leave as unformatted number ;
put _all_;
run; * x=01JAN1960:14:12:15 y=51135 ;

and end up with

if mydate > 51135 then mydate = datepart(mydate);

(so still no magic)

Now many times DATEs are for DOB etc with values back to,
and prior to, 1960 and this suggestion is quite silly.
However, the point is that with the comfortable understanding
of how days and seconds are stored in a number, for the different
units of measure, -and- if you know your data well, you may
have the *opportunity* to utilize some arithmetic scheme to
allow you the luxury of coming up with something smooooth!

(if you have such circumstances that would allow something
tricky then you WILL have made some *magic*)


Hope this is helpful,
Mark Terjeson
Reporting, Analysis, and Procurement Section
Information Services Division
Department of Social and Health Services
State of Washington
mailto:***@dshs.wa.gov






-----Original Message-----
From: VP1695 [mailto:***@AOL.COM]
Sent: Friday, July 09, 2004 5:34 AM
To: SAS-***@LISTSERV.UGA.EDU
Subject: DATEPART function

I just wanted to warn those of you who use the DATEPART function.
As many of you know, this function extracts the date from a SAS
datetime value. However, if you use DATEPART on the date (not
datetime) variable, the value of the function will become 0 which
corresponds
to 01JAN1960
in SAS. Why would anybody want to use this function on the date? Well, I'll
give you a scenario. Let's say you extract data from Oracle using PROC SQL.
For some reason, SAS treats Oracle dates as datetime variables, and if you
want dates you may decide to use the DATEPART function in your SAS code.
Now, say, at some later point your database, data warehouse,... migrates to
another platform, say, Teradata. You are unaware that SAS reads Teradata
dates as dates and are using the same SAS code with the DATEPART functions
in it. It would be nice if SAS warned you that the argument of the DATEPART
function is invalid, but SAS doesn't give either an error message or at
least a warning and you are getting 01JAN1960 all over without even knowing
it.

Vadim Pliner
Chang Y. Chung
2004-07-10 03:30:27 UTC
Permalink
Post by VP1695
Hi Chang,
I do remember that SAS has only two different data types: numeric and
character and there are no date types in SAS. However, I don't
understand why
Post by VP1695
"it is simply impossible for sas to warn" about a potential misuse of the
DATEPART function. You are right, all date and datetime variables are
numeric,
Post by VP1695
but their formats are different. Why couldn't SAS tell a date format from
a
Post by VP1695
datetime one? Even if it was impossible, is it logical that the DATEPART
of any
Post by VP1695
date (numeric variable formatted as a date) is 0 i.e. '01JAN1960'?
Hi, Vadim,

Yes. You are correct - it is possible. Maybe we need two functions:
datePartX() that takes a numeric expression, and safeDatePart() which
takes only either a dt literal or a numeric variable with a dt-type
format.

Wait! We may probably need two more functions: safeDatePartE(), which
checks the format of the input variable during the execution time; and
safeDatePartC(), which does it in the compile time.

While we are at it, why don't we ask sas for two more? safeDatePartEN(),
which returns a numeric variable formatted with a date format which is
most compatible with the datetime format of the input variable, and
safeDatePartEC(), which returns a character string of the date value
already formatted with the associated format.

Hmmm, we may need two more because we have the C versions: safeDatePartCN
() and safeDatePartCC()

Well, how many (data step) functions we already have? Do you remember the
exact difference between vlabel() and vlabelx()? How about cat...()
family? Why can't we write our own functions using data step language?
... We may be better off just asking sas for the genuine, date, time, and
datetime types. ... Oh, wait, if we have them ... then, how many more
input...() and put...() family functions should we have? ... how the
automatic conversion (or type-promotion) rules would read like?

Happy Friday!

Cheers,

Chang
Richard A. DeVenezia
2004-07-10 12:59:38 UTC
Permalink
Post by VP1695
I just wanted to warn those of you who use the DATEPART function.
Thank you for the warning.
The migration process should have considered warehouse usage and undesired
side effects.
<harsh>
Oracle date type is a datetime value, Teradata date type is a date value.
Dont use DatePart function with date values.
A joy of speciation is that different things are indeed different and
require understanding
Also, a warning for US drivers: when in the UK, look out. They drive on the
wrong side of the road.
p.s. Mosquito repellent isn't working against bees.
Snif, our shiny new Maserati bottoms out on the same road our old Jeep
didn't.
</harsh>
--
Richard A. DeVenezia
Howard Schreier
2004-07-11 03:10:57 UTC
Permalink
You can write your own safety net using the VFORMATN function to examine
the format associated with a variable. But that's not a sure thing. A
variable does not have to have a format, and in particular datetime
variables work very nicely in internal calculations regardless of whether
they have formats (which are basically for presentation). Also keep in mind
that it's a carpenterian (as in
http://www2.sas.com/proceedings/sugi23/Training/p275.pdf) "best" practice
to store variables with associations to utterly inappropriate formats, then
apply the appropriate ones on the fly (of course by means of intricate and
obscurely named macros).
Post by VP1695
Hi Chang,
I do remember that SAS has only two different data types: numeric and
character and there are no date types in SAS. However, I don't understand
why
Post by VP1695
"it is simply impossible for sas to warn" about a potential misuse of the
DATEPART function. You are right, all date and datetime variables are
numeric,
Post by VP1695
but their formats are different. Why couldn't SAS tell a date format from a
datetime one? Even if it was impossible, is it logical that the DATEPART
of any
Post by VP1695
date (numeric variable formatted as a date) is 0 i.e. '01JAN1960'?
Vadim
Post by VP1695
Post by VP1695
I just wanted to warn those of you who use the DATEPART function.
As many of you know, this function extracts the date from a SAS
datetime value. However, if you use DATEPART on the date (not
datetime) variable, the value of the function will become 0 which
corresponds
Post by VP1695
to 01JAN1960
in SAS. Why would anybody want to use this function on the date? Well,
I'll
Post by VP1695
give you a scenario. Let's say you extract data from Oracle using PROC
SQL.
Post by VP1695
For some reason, SAS treats Oracle dates as datetime variables, and if
you
Post by VP1695
Post by VP1695
Post by VP1695
want dates you may decide to use the DATEPART function in your SAS code.
Now, say, at some later point your database, data warehouse,... migrates
to
Post by VP1695
another platform, say, Teradata. You are unaware that SAS reads Teradata
dates as dates and are using the same SAS code with the DATEPART
functions
Post by VP1695
Post by VP1695
Post by VP1695
in it. It would be nice if SAS warned you that the argument of the
DATEPART
Post by VP1695
function is invalid, but SAS doesn't give either an error message or at
least a warning and you are getting 01JAN1960 all over without even
knowing
Post by VP1695
it.
Vadim
Hi, Vadim,
I can understand the pain when you must have felt when you discovered that
the migrated data are incorrect.
Transferring (or migrating) data from one system to another, however, are
inherently difficult, in my opinion, because it requires the user to be
familiar with both the systems that are involved, plus whatever the
software tool or standard that are used in the process. This also means
that as long as different systems are involved, there are no reasons to
assume that the transfer code you wrote would work the same way as it did
before with a different system.
The best kind of transfer software tools, IMHO, let you specify, for each
var, the exact data types to be used on both input and output sides; it
should also let you spell out on which side the data type conversion
should occur and in which fashion. I am quite pleased with some of the
sas/access products in this regard.
The worst kind is the ones that try to be "smart" and hide all the details
from the user or, worse, do not allow such detailed user control over the
transfer process. Alas, it seems to me that the latter, rather then the
former, is the more popular kind.
Regarding the sas's datepart function, you may benefit from reminding
yourself that sas has only two different data types: numeric and
character. There are no date types. As such, the input to the datepart
function is simply a numeric type variable. Thus it is simply impossible
for sas to "detact" or "warn" user about the possible abuses like you
mention.
Hope this helps and good luck with your data migration in the future.
Cheers,
Chang
Droogendyk, Harry
2004-07-12 13:15:39 UTC
Permalink
I realize this doesn't help Vadim right now, but it may be helpful to others
who access Oracle from SAS.

The datetime values returned by SAS when accessing Oracle aren't
particularly helpful in my experience ( i.e. the time portion is always zero
).

Rather than dealing with the datepart() function in SAS, I found it helpful
to convert the Oracle date value to a SAS date value in the pass-thru query
using a simple little macro.

Note that infld can be table.fieldname notation and, optionally, outfld can
be specified if a different field name is required in the output dataset.


%macro to_sasdate(infld,outfld);
%if &outfld = %str() %then %let outfld = &infld;
%if %index(&outfld,.) %then %let outfld = %scan(&outfld,2,.); /* if
table_name.column, strip table_name */

&infld - to_date('01jan1960','ddmonyyyy') as &outfld

%mend to_sasdate;

proc sql;
connect to oracle ( );
create table saslib.sasdata as
select * from connection to oracle (
select field1
,field2
,%to_sasdate(oracle_date_field)
,field3
from oracle_table )
;
disconnect from oracle;
quit;

-----Original Message-----
From: VP1695 [mailto:***@AOL.COM]
Sent: Friday, July 09, 2004 8:34 AM
To: SAS-***@LISTSERV.UGA.EDU
Subject: DATEPART function


I just wanted to warn those of you who use the DATEPART function.
As many of you know, this function extracts the date from a SAS
datetime value. However, if you use DATEPART on the date (not
datetime) variable, the value of the function will become 0 which
corresponds
to 01JAN1960
in SAS. Why would anybody want to use this function on the date? Well, I'll
give you a scenario. Let's say you extract data from Oracle using PROC SQL.
For some reason, SAS treats Oracle dates as datetime variables, and if you
want dates you may decide to use the DATEPART function in your SAS code.
Now, say, at some later point your database, data warehouse,... migrates to
another platform, say, Teradata. You are unaware that SAS reads Teradata
dates as dates and are using the same SAS code with the DATEPART functions
in it. It would be nice if SAS warned you that the argument of the DATEPART
function is invalid, but SAS doesn't give either an error message or at
least a warning and you are getting 01JAN1960 all over without even knowing
it.

Vadim Pliner

------------------------------------------------------------This e-mail may be privileged and/or confidential, and the sender does not waive any related rights and obligations. Any distribution, use or copying of this e-mail or the information it contains by other than an intended recipient is unauthorized. If you received this e-mail in error, please advise me (by return e-mail or otherwise) immediately.

Ce courrier électronique est confidentiel et protégé. L'expéditeur ne renonce pas aux droits et obligations qui s'y rapportent. Toute diffusion, utilisation ou copie de ce message ou des renseignements qu'il contient par une personne autre que le (les) destinataire(s) désigné(s) est interdite. Si vous recevez ce courrier électronique par erreur, veuillez m'en aviser immédiatement, par retour de courrier électronique ou par un autre moyen.

============================================================
Gerstle, John
2004-07-12 13:29:55 UTC
Permalink
Another idea that may be useful for keeping dates 'stable' across database software, would be to convert the date into text before transferring the data. This would require re-converting any and all date variables, but could be a useful workaround. I personally don't like date variables as text but it can come in handy at times.

John Gerstle
CDC Information Technological Support Contract (CITS)
Biostatistician
Post by Terjeson, Mark
-----Original Message-----
Droogendyk, Harry
Sent: Monday, July 12, 2004 9:16 AM
Subject: Re: DATEPART function
I realize this doesn't help Vadim right now, but it may be helpful to
others
who access Oracle from SAS.
The datetime values returned by SAS when accessing Oracle aren't
particularly helpful in my experience ( i.e. the time portion is always
zero
).
Rather than dealing with the datepart() function in SAS, I found it
helpful
to convert the Oracle date value to a SAS date value in the pass-thru
query
using a simple little macro.
Note that infld can be table.fieldname notation and, optionally, outfld
can
be specified if a different field name is required in the output dataset.
%macro to_sasdate(infld,outfld);
%if &outfld = %str() %then %let outfld = &infld;
%if %index(&outfld,.) %then %let outfld = %scan(&outfld,2,.); /* if
table_name.column, strip table_name */
&infld - to_date('01jan1960','ddmonyyyy') as &outfld
%mend to_sasdate;
proc sql;
connect to oracle ( );
create table saslib.sasdata as
select * from connection to oracle (
select field1
,field2
,%to_sasdate(oracle_date_field)
,field3
from oracle_table )
;
disconnect from oracle;
quit;
-----Original Message-----
Sent: Friday, July 09, 2004 8:34 AM
Subject: DATEPART function
I just wanted to warn those of you who use the DATEPART function.
As many of you know, this function extracts the date from a SAS
datetime value. However, if you use DATEPART on the date (not
datetime) variable, the value of the function will become 0 which
corresponds
to 01JAN1960
in SAS. Why would anybody want to use this function on the date? Well,
I'll
give you a scenario. Let's say you extract data from Oracle using PROC
SQL.
For some reason, SAS treats Oracle dates as datetime variables, and if
you
want dates you may decide to use the DATEPART function in your SAS code.
Now, say, at some later point your database, data warehouse,... migrates
to
another platform, say, Teradata. You are unaware that SAS reads Teradata
dates as dates and are using the same SAS code with the DATEPART
functions
in it. It would be nice if SAS warned you that the argument of the
DATEPART
function is invalid, but SAS doesn't give either an error message or at
least a warning and you are getting 01JAN1960 all over without even
knowing
it.
Vadim Pliner
------------------------------------------------------------This e-mail
may be privileged and/or confidential, and the sender does not waive any
related rights and obligations. Any distribution, use or copying of this
e-mail or the information it contains by other than an intended recipient
is unauthorized. If you received this e-mail in error, please advise me
(by return e-mail or otherwise) immediately.
Ce courrier électronique est confidentiel et protégé. L'expéditeur ne
renonce pas aux droits et obligations qui s'y rapportent. Toute
diffusion, utilisation ou copie de ce message ou des renseignements qu'il
contient par une personne autre que le (les) destinataire(s) désigné(s)
est interdite. Si vous recevez ce courrier électronique par erreur,
veuillez m'en aviser immédiatement, par retour de courrier électronique
ou par un autre moyen.
============================================================
Continue reading on narkive:
Loading...