Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

ISO Weeks 2

Status
Not open for further replies.

Tarwn

Programmer
Mar 20, 2001
5,787
US
I'd like to see some code for finding ISO Weeks :)

I have a stored proc here at work that runs the fairly standard Microsoft example of how to get an ISO weeks with lots of DatePart goodness and multiple lines...

Lets see who can make the:
Shortest line count, any language (not counting function declaration)
Shortest character count, any language (not counting function declaration)
Most efficient SQL Proc that may end up replacing the one we have now since I don't have the time to play with it myself :)


Information on ISO Weeks:
-T

signature.png
 
sorry, forgot one backslash after the first single code line, messed up my posting.

Bye, Olaf.
 


Olaf

The WEEK() function does not exist in FP 2.6 so I can not use it to find any of the many ways to calculate any part of the week. I have no idea when it was first included in FP, so it may not be an option for many people.

Quote from above:

But it's still cheating to use a built-in function, where's the fun in that? :D

And finally, even if WEEK() was available in FP 2.6, I don't see how it could easily be used to find the first day of the ISO year whereas the WK1DATE() function I wrote above returns the first day of any ISO year when passed the year in question, i.e. 2006 or whatever.

Even though I can't use it, just the fact that you have enlightened us with another obscure, but very useable function, earns you a star.



mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
mmerlin,

FP 2.6 is very old and not even supported anymore. The Week() function is this way as long as I know VFP, that startet with VFP6. So very many Foxpro users can make use of it, as most of them nowadays use VFP8 or 9.

First day of the iso year? Well, compute the week of the 1.1. of the year in question. if it's the 1. week of that wear, subtract the difference to monday, if it's >1 then add the difference in days to monday. Easy.

Bye, Olaf.
 
Olaf,

Ja, FP 2.6 is old and unsupported, but some of us, including me, are stuck with it for several reasons. One, many existing working programs are not cost-effective to rewrite. Two, anyone using a Mac or Unix system cannot upgrade to later versions of FP. Three, at my age, I see no point in learning OOP as the learning curve is longer than my estimated working life.

Since FP 2.6 will exist long after I die, it makes more sense for me continue with what I 'know' (ha-ha-ha), than to migrate to a technology that I will never have a chance to master. So I will continue with the old, and when I see something in the new that will help with the old, I will hijack it for use with the old.


mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
Hi merlin,

that's okay with me. But you said it may not be an option for many people. I couldn't let that stand uncommented.

It may be an option for few, as vfp is not very spread, still it's rising high in the tobe index of programmer communities: currently ranking 14th right after Ruby and before VB.net.

Bye, Olaf.
 
Here's the shortest VB6 code I could craft. It uses just one built-in date function to get the first day of the year.

Code:
Public Function ISOWeek(D As Date) As Long
    Dim D2 As Date
    D = D - (D - 2) Mod 7 + 3
    D2 = DateSerial(Year(D), 1, 1)
    D2 = D2 + 6 - (D2 - 6) Mod 7
    ISOWeek = (D - D2) \ 7 + 1
End Function

To compete for shortest code, I'll eliminate variables or types to get 147 characters, not counting carriage returns or indent spaces:

Code:
Public Function ISOWeek(D)
    D = D - (D - 2) Mod 7 + 3
    D2 = DateSerial(Year(D), 1, 1)
    D2 = D2 + 6 - (D2 - 6) Mod 7
    ISOWeek = (D - D2) \ 7 + 1
End Function

Getting it on three lines is easy: just put colons between statements. :)

Here's a SQL Server version for your pleasure.

Code:
CREATE FUNCTION ISOWeek (@TheDate smalldatetime)
RETURNS int
AS
BEGIN
   DECLARE @D int, @D2 int
   SET @D = Convert(int, DateAdd(dd, DateDiff(dd, 0, @TheDate), 0))
   SET @D = @D - @D % 7 + 3
   SET @D2 = Convert(int, DateAdd(yy, DateDiff(yy, 0, DateAdd(dd, @D, 0)), 0))
   SET @D2 = @D2 + 6 - (@D2 - 4) % 7
   RETURN (@D - @D2) / 7 + 1
END

I'll be interested to see if I made any mistakes!

Erik
 
Hi all,

to somehow really earn the star, here's my vfp solution, not using some special vfp function like week() or dow() (day of week), just using Year(), returning the year of some date, Date(), which is equal to VBs DateSerial() and using date differences, which in vfp can simply be calculated by subtracting two variables or expressions of the date type. These operations should be available in any programming language or be implemented easily.

I also use two constant dates: 31st december 1999 is a friday therefore 3rd january 2000 is a monday. Those could be replaced by any monday or friday. Or even substitute expressions like (date-dateconstant)%7 through some dayofweek function, that returns values from 0 to 6, 0 being the same weekday as the dateconstant.

Code:
Function isoWeek(tdDate)
   Local ldLastmonday, ldNewyear, ldFirstMonday
   * monday of the same week as tdDate:
   ldLastmonday = tdDate-(tdDate-Date(2000,1,3))%7 
   * newyear of the year of the thursday of the same week:
   ldNewyear = Date(Year(ldLastmonday+3),1,1)
   * first monday of that isoyear:
   ldFirstMonday = ldNewyear+3-(ldNewyear-Date(1999,12,31))%7
   * isoweek:
   Return Int((ldLastmonday-ldFirstMonday)/7)+1
EndFunc

That can be shortened by using short var names and substituting ldNewyear into the line computing the first monday (f):
Code:
Function isoWeek(d)
   l = d-(d-Date(2000,1,3))%7
   f = Date(Year(l+3),1,1)+3-(Date(Year(l+3),1,1)-Date(1999,12,31))%7
   Return Int((l-f)/7)+1
EndFunc

Bye, Olaf.
 
Olaf,

Our solutions are basically identical in their method... interesting. Date arithmetic is convenient!

I didn't think about the fact that I could use other days besides Thursday for the week day comparison part, so I thought at first that my function might be able to drop an operation by trying other days until an operand comes out to be 0. But then I realized that by using Monday instead of Thursday, you had to add +3 Year(l+3)... hmmm.

You probably know this, but you could simplify by changing
Date(2000,1,3)
and
Date(1999,12,31)
to their integer values modulo 7, whatever that comes out to in VFP. Of course this makes porting to other languages more difficult, but is more optimized for the specific language.
 
Hi Erik,

yes, quite the same idea.

hmm, yes, to compute the weeks thursday in the first place, instead of the weeks monday I could drop the +3 for computing the iso years new year day, true. int((thisweeksthursday-firstmondayofisoyear)/7)+1 would still be the correct return value.

In vfp you cannot compute SomeDate()%7. The date type surely is some number internally, but vfp does not allow this kind of expression. I first have to compute a difference between two dates in days, then can take modulo 7 from that.

However vfp has a julian day function. It's a bit ugly, as it returns the julian day number as a string, might still be faster to compute (Val(sys(11,somedate))+n)%7 instead of (somedate-constantdate)%7.

But as said I could also simply use the day of week function DOW(), returning 1 to 7 for whatever day I determine to be the first weekday, I intentionally not used that function. I thought a date difference might be a more basic calculation you could translate to other languages.

Bye, Olaf.
 
Much Much better than my previous solution, good job to both of you guys. I'm definately going to dig into the logic behind them when I am a little less tired.

And thats why I like these kinds of problems, they make us stretch our intellect to continually simplify the complex until you end up with a very complex simplification :)

 
Tarwn said:
until you end up with a very complex simplification :)
Yes, simplifications that work and you can't easily explain why. It's a bit dangerous.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top