BookmarkSubscribeRSS Feed
Pavan_SAS
SAS Employee
data san;
input @ 1 from_dt date9. @ 11 to_date date10. ;
cards ;
01jan1382 01jan20001
01jan1082 01dec20001
01jan1882 01jan20000
01jan1582 01jan2001
;
run ;
10 REPLIES 10
Doc_Duke
Rhodochrosite | Level 12
I think that you are SOL. From the SAS Base documentation:

SAS date value
is a value that represents the number of days between January 1, 1960, and a
specified date. SAS can perform calculations on dates ranging from A.D. 1582 to
A.D. 19,900.

The reason for this is that, when the dates are stored as durations, that range is the widest that can be precisely expressed in real number format in 8 bytes.

Doc Muhlbaier
Duke
Pavan_SAS
SAS Employee
i know this !
but for my one of the project i have to play with such type of dates.
now how can i handle this?

no solution in sas?
darrylovia
Quartz | Level 8
I believe there is no solution period. Here is why, the calendar used today is the Gregorian Calendar which came into effect in 1582 AD (hmm where have we seen that before?), which most likly why SAS uses that as the date floor. Before the Gregorian Calendar the western world used the Julian Calendar which among other things treats leap days, number of days in a month different than the calendar used today. Hence a monday could be a tuesday if you compare a Julian date with a Gregorian date and the year could have a different number of days.

Gregorian dates before 1582 use something called the proleptic Gregorian calendar. Unfortunately, I don't SAS can use that calendar (there may be a custom calendar functionality but I don't know about it) Since SAS dates will not go before 1582, you will have to find a custom solution.

My first suggestion would be to find Julian day number to Gregorian mapping table (GOOGLE it and see what you find) and treat the days as integers and not dates. A Julian day number is not the same thing as the Julian Calendar it is the number days since 1/14713 BC, not sure why that day was picked . You will have to construct your own "date" format to display it. Just a guess, I haven't tried to go that far back in time with SAS.

I wish I could be more helpful.
-Darryl
Cynthia_sas
SAS Super FREQ
Hi:
Oh, my, I had NO idea there was this much possibility of variation in dates. These make for interesting reading and the last link has a formula and some lookup tables.
http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html
http://charon.nmsu.edu/~lhuber/leaphist.html
http://www.decimaltime.hynes.net/dates.html
http://www.decimaltime.hynes.net/convert.html (has a Gregorian to Julian conversion formula)

cynthia
Olivier
Pyrite | Level 9
Hi Pavan.
I would try something quite different : store separately day, month & year instead of trying to build a real date. You can compute durations (though it will be a little more complicated that using built-in SAS function) but usually this is enough to get trhough common needs.
[pre]
proc format ;
invalue months
"jan" = 1
"feb" = 2
"mar" = 3
"apr" = 4 /* and so on */
"dec" = 12
;
run ;
data san;
input @1 from_dd 2. from_mm months. from_yy 4. @11 to_dd 2. to_mm months. to_yy :5. ;
cards ;
01jan1382 01jan20001
01jan1082 01dec20001
01jan1882 01jan20000
01jan1582 01jan2001
;
run ;
[/pre]
Regards.
Olivier
Pavan_SAS
SAS Employee
by using this, i can read this dates into sas.
but to do some analysis like date difference and something, how i can do?
if these dates will enter into sas dataset, like numer of dates from 1jan1960,
then it is good to do some analysis!

i want to take these dates as no. of days from 1jan1960.
Pavan_SAS
SAS Employee
i got the solution !

data san;
length from_dt to_date $10;
input from_dt $ : to_date $ : ;
if input(substr(from_dt,6),best.) lt 1582 then do;
days_in_loop=0;
days_till_1582='01jan1582'd;
do i=input(substr(from_dt,6),best.) to 1581;
if mod(i,4)=0 then days_in_year=366;
else days_in_year=365;
days_in_loop=days_in_loop-days_in_year;
end;
from_dt1=days_till_1582+days_in_loop;
end;
else from_dt1=input(from_dt,date9.);
to_date1=input(tranwrd(to_date,'000','00'),date9.);
keep to: from: ;
cards ;
01jan1382 01jan20001
01jan1082 01dec20001
01jan1882 01jan20000
01jan1582 01jan2001
01jan1581 01jan20003
;
run ;
jbhan
Calcite | Level 5
Your leepyear algorithm is too crude - it is not simply every 4 years. Can't recall the exact rules, but did code it up once. A quick google should help you out
DouglasMartin
Calcite | Level 5

Leapyears are every four years EXCEPT for century years which are only leapyears if they are divisible by 400. So, 2012 is a leap year (divisible by 4), 1900 was not a leapyear (it was a century year but was not divisible by 400), 2000 was a leapyear (century year divisible by 400).

AllenEBingham
Calcite | Level 5

Although --- this is a bit off topic by now, since I'm fairly certain that darrylovia's answer means that treating the days before 1582 as if they came from current-day calendar practices is essentially wrong ... I thought I'd share my leap year code logic (operates on the year in four digits ... so you'd need to get the year from the SAS date value first):

      /* The following is the beginning snippet of code that defines a year as a leap year */

    

         IF (MOD(YEAR,100) NE 0 AND MOD(YEAR,4) EQ 0) OR (MOD(YEAR,400) EQ 0) THEN

... I think this handles when leap years occur in the modern calendar.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 10 replies
  • 2244 views
  • 0 likes
  • 8 in conversation