At 1:10 PM +0300 9/5/01, Douglas Wagner wrote:
>Hello Raymond:
>
>Here is an AppleScript I use to calculate an European date. If you can pack
>this into 10 lines I will take off my hat to you.
>

(Raymond, I hope you don't mind -- I couldn't resist the challenge)

If I understand correctly, and my code has no bugs, here is a solution that is just 10 
lines. It might not be as clear as it could, but it won't win any obfuscated code 
contests either. One of the confusing aspects of the solution is that Euro dates 
number from Monday, while Revolution numbers from Sunday. That's what all the 'item 
(item 7 of tDate) of "2,3,4,5,6,7,1' stuff is about.

If I haven't understood correctly, let me know.

This took about two hours to write. That's pretty inefficient from a lines/hour 
standpoint, but I don't know if I could have written a more verbose version in less 
time. A fair portion of the time was just trying to figure out what the right thing to 
do with days at the beginning and end of years was.

If anyone can shorten the script, speak up. It only just fit, so I'd love to see it 
get shorter :-)

Here it is, with minimal comments (note that "\" is used for line continuations):

function convertDate tDate
 --takes any date format Rev accepts,
 --and converts to yyyy-Www-d format,
 --where yyyy is the four digit year
 --ww is the week of the year
 --and d is the day of the week
 
 --note: weeks always start on Monday
 --Monday is day 1, Tuesday is day 2, etc.
 
 --also, a week falls in the year where
 --its Thursday falls.
 --In other words, if January 1st, 2000 is a Friday,
 --then it would result in something like
 --1999-W53-5, not a date in 2000
 --in the same way, December 31st, 2000, if it were
 --a Tuesday, would be 2001-W01-2
 
 --here's the code:
 -----------------------------------------------------
 --1. get the date in a safe format
 convert tDate to dateitems
 
 --2. get the Jan 1st of the year of the date:
 put "1/1/" & (item 1 of tDate) into tStartDate 
 
 --3. if the date is at the beginning of the year
 --and the week wraps into previous year, then
 --set the start of the year to Jan 1st of the previous year:
 if ((item 2 of tDate is 1) and \
   ((item (item 7 of tDate) of "8,2,3,4,5,6,7") - (item 3 of tDate) > 4)) \
   then put ("1/1/" & ((item 1 of tDate) - 1)) into tStartDate
 
 --4. likewise, if the date is at the end of the year
 --and the week wraps, then set the start of the year to
 --jan 1st of the next year:
 if ((item 2 of tDate is 12) and \
   ((item 3 of tDate) - (item (item 7 of tDate) of "8,2,3,4,5,6,7") > 26)) \
   then put ("1/1/" & ((item 1 of tDate) + 1)) into tStartDate
 
 --5. get the year and the day of the week that we will return:
 put ((char -4 to -1 of tStartDate) & "-W,-" & \
   (item (item 7 of tDate) of "7,1,2,3,4,5,6")) into tReturn
 
 --6. get the date items of the start of the year
 --this is in order to get the day of the week
 --of jan 1st of the year.
 convert tStartDate to dateitems
 
 --7. get the offset based on the day of the week of jan 1st :
 put (item (item 7 of tStartDate) of "-1,0,1,2,3,-3,-2") into tOffset
 
 --8. convert the date to seconds (I like seconds)
 convert tDate to seconds
 
 --9. convert jan 1st of the start year to seconds
 convert tStartDate to seconds
 
 --10. return the result. the week of the year,
 --including the offset, is calculated as part of this.
 return ((item 1 of tReturn) & (char -2 to -1 of \
   ("0" & ((((tDate - tStartDate)/86400) + tOffset) div 7) + 1)) & \
   (item 2 of tReturn))
end convertDate


>
>**********
>set theDate to current date
>property Y : ""
>property M : ""
>property D : ""
>property leapYear_Y : false
>property leapYear_Yminus1 : false
>property theEuroDate : ""
>
>--1 GET THE DATE ITEMS
>--day number with leading zero
>set D to text -2 thru -1 of ("0" & theDate's day)
>--month number with leading zero
>copy theDate to b
>set month of b to January
>set M to text -2 thru -1 of ("0" & (1 + (theDate - b + 1314864) div 2629728))
>-- make the string
>set Y to text -4 thru -1 of ((year of theDate) as text)
>
>--2 FIND IF Y IS A LEAPYEAR
>if ((Y mod 4 = 0) and (Y mod 100 � 0)) or Y mod 400 = 0 then set leapYear_Y
>to true
>
>--3 FIND IF Y-1 IS A LEAPYEAR
>if ((Y mod 4 = 0) and (Y mod 100 � 0)) or Y mod 400 = 0 then set
>leapYear_Yminus1 to true
>
>--4 FIND THE DayOfYearNumber for Y, M and  D
>set mnthNum to {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}
>set mm to M as integer --strip the leading zero for the test
>if (mm < 1) or (mm > 12) then
>   error "Out of Range" number 20001
>else
>   set DayOfYearNumber to D + (item M of mnthNum)
>end if
>if leapYear_Y and M > 2 then set DayOfYearNumber to DayOfYearNumber + 1
>
>--5 FIND THE Jan1Weekday for Y (Monday=1, Sunday=7)
>set yy to (Y - 1) mod 100
>set C to (Y - 1) - yy
>set g to yy + yy / 4
>set Jan1Weekday to 1 + (((((C / 100) mod 4) * 5) + g) mod 7)
>
>--6 Find the Weekday for Y M D
>set H to DayOfYearNumber + (Jan1Weekday - 1)
>set dayOfWeek to 1 + ((H - 1) mod 7)
>
>--7 Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53
>if (DayOfYearNumber � (8 - Jan1Weekday)) and (Jan1Weekday > 4) then
>   set YearNumber to Y - 1
>   if (Jan1Weekday = 5) or ((Jan1Weekday = 6) and leapYear_Yminus1) then
>      set weekNumber to 53
>   else
>      set weekNumber to 52
>   end if
>else
>   set YearNumber to Y
>end if
>
>--8 Find if Y M D falls in YearNumber Y+1, WeekNumber 1
>if YearNumber = Y then
>   if leapYear_Y then
>      set I to 366
>   else
>      set I to 365
>   end if
>   if (I - DayOfYearNumber) < (4 - dayOfWeek) then
>      set YearNumber to Y + 1
>      set weekNumber to 1
>   end if
>end if
>
>--9 Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
>if YearNumber = Y then
>   set J to DayOfYearNumber + (7 - dayOfWeek) + (Jan1Weekday - 1)
>   set weekNumber to J div 7
>   if Jan1Weekday > 4 then
>      set weekNumber to weekNumber - 1
>   end if
>end if
>
>--10 Output ISO Week Date
>if weekNumber < 10 then
>   set weekNumber to "0" & weekNumber --(WeekNumber requires 2 digits)
>end if
>--(Optional: "W" & WeekNumber)
>set theEuroDate to YearNumber & "-W" & weekNumber & "-" & dayOfWeek
>
>
>
>**********

Reply via email to