Det er ikke svært f.eks. at lave en funktion, der givet nummeret på en måned og årstallet vil returnere en tekst streng som f.eks. "10,11,12,13,14". Den første uge i januar er jo bestemt ved DatePart("ww","01-01-2004",vbMonday,vbFirstFourDays) og den sidste ved DatePart("ww","31-01-2004",vbMonday,vbFirstFourDays) og så videre. Ville du være interesseret i en sådan funktion?
>Nute den virker!!! men nu har jeg sat nmh i sving med at lave mig en funktion… så jeg man lige respektere hans ud kast først, ellers ville jeg mene det er fair vis i deler pointene! Ikk’
Her er den. Jeg blev lige opholdt af noget andet, så det tog lidt tid. (Den sidste linie er kun for at teste som et alm. VBscript.) Option Explicit function skudaar(aar) dim nr skudaar=True on error resume next nr=DatePart("ww","29-02-" & aar,vbMonday,vbFirstFourDays) if err.number>0 then skudaar=False end function
function Ugenumre(maaned,aar) dim dage(12), min, max, i, t dage(1)=31:dage(2)=28:dage(3)=31: dage(4)=30:dage(5)=31:dage(6)=30: dage(7)=31:dage(8)=31:dage(9)=30: dage(10)=31:dage(11)=30:dage(12)=31: if skudaar(aar) then dage(2)=29
min=DatePart("ww","01-" & maaned & "-" & aar,vbMonday,vbFirstFourDays) max=DatePart("ww",dage(maaned) & "-" & maaned & "-" & aar,vbMonday,vbFirstFourDays) for i=min to max t=t & i & "," next ugenumre=t end function
Nute> Jeg kan kun få dit script til at virke, hvis årstallet er 2004. For andre år skriver den kun et enkelt ugenummer ud. 2003 f.eks, men 2008 så går det godt. Mon ikke der er problemer i forbindelse med skudår?
ups ... der var en lille bug i min ... denne linie:
Dim objEndDate : objEndDate = DateAdd( "d", 28, objStartDate )
skal være
Dim objEndDate : objEndDate = DateAdd( "d", 27, objStartDate )
Der er ingen problemer med skudår. Hele humlen, er at der startes på en dato (den første i den måned du angiver), lægger 27 dager til denne dato og derefter en og en dag for at finde når den første i næste måned er. når jeg har fundet den første i næste måned, så ved jeg hvor mange dage det er i den måned jeg angav, og så er resten lige ud af landevejen. Det er ingen grund til at gøre som nmh (no offence nmh), for systemet ved allerede hvor skudår ligger hen. Det eneste man skal finde ud af, er den sidste dagen i måneden. prøv at skifte den linie jeg har skrevet du skal skifte, og du vil se at det fungerer
Nute> Ja systemet ved da heldigvis, hvornår det er skudår. men jeg var nødt til at finde en nem måde at afgøre om februar havde 28 eller 29 dage. Men at afgøre hvilke ugenumre, der er i en given måned er desværre lidt mere indviklet end som så :o).
Nu har jeg fundet definitionen på ugenummer frem. Den er her:
ISO standard 8601:1988 - (European Standard EN 28601). Contains information on how to format date/time representations, the leap years, etc., It states that a week is identified by its number in a given year. A week begins with a Monday (day 1) and ends with a Sunday (day 7). The first week of a year is the one which includes the first Thursday (day 4), or equivalently the one which includes January 4.
In other words, the first week of a new year is the week that has the majority of its days in the new year.
Note:
i) Week 01 might contain days from the previous year, ii) The week prior to week 01 of a year is the last week (52 or 53) of the previous year (even if it contains days from the new year).
I år 2000 er 1. januar en lørdag. Dvs. uge 1 begynder derfor mandag den 03.01.2000. Og januar måned indeholder altså uge 52 fra år 1999. Det skal jo ikke være for let. ;o)
Mit script skal derfor have en lille tilføljelse: Lige før for-løkken
for min=1 to max
skal tilføjes:
if maaned=1 and min<>1 then t=min & "," min=1 end if
På den måde vil januar i år 2000 indholde ugenumrene: 52,1,2,3,4,5 og februar vil indeholde ugenumrene 5,6,7,8,9.
nute's script giver januar 2000: 1,2,3,4,5,6 februar 2000: 5,6,7,8,9
Det ærgrer mig dog at jeg glemte, at der også kunne være problemer i slutningen af året, hvor uge nr. 1 kan være med i december. For god ordens skyld laver jeg en rettelse senere. :o) Jeg har ikke tid nu.
nmh >> ja, ok ... men hvem i hulen går med den definition af en uge i hovedet ?? :-D En uge for mig, er "hvor mange mandager har der været i det år jeg befinder mig i" (( uge 1 vil jo eksistere selv om den ikke indeholder en manag, men dette kalder jeg så en 'ubetydelighed' i den store sammenhæng :o] )) ... men jeg kan godt se din pointe. Jeg er dog stadig "uening" i dit løsningsforslag - jeg kan ikke se nødvendigheden i at fortælle systemet noget den allerede ved. Jeg kan selvfølgelig tage fejl ... men det finder jeg jo ud af (( er nødt til at teste lidt mere )) :o]
/nute
PS! En lille rettelse til hvad mit script viser ... februar 2000, viser *ikke* 5 som en del af ugenumre ... februar 2000 starter i uge 6 (( som den også gør i mit hovede ... nu og for altid ;o] ))
nute>> Ja, jeg kom til at lave en skrivefejl mht uge 5 i februar år 2000 for din løsning. Beklager.
Jeg er heller ikke helt tilfreds med min løsning, men fordi jeg bygger den på at lade funktionen datepart returnere et ugenummer, var det den simpleste måde at lave det på. Jeg går heller ikke rundt og husker på ugenummer-funktionen, og jeg er da blevet lidt overrasket over hvor kompliceret problemet egentlig er.
Det viser sig, at der er en fejl hos Microsoft: Se http://www.eksperten.dk/spm/474320 hvor Eagleeye giver en reference. Det script, jeg henviser til dette sted, har jeg dog ikke kunnet finde fejl i. DatePart("ww","29-12-2003",vbMonday,vbFirstFourDays) giver resultatet 53 istedet for det korrekte, som er 1.
Her er så en ny version, der tager højde for den fejl, der er hos Microsoft i funktionen Datepart(...). Jeg har brugt Microsofts forslag til at rette fejlen. Funktionen WOY(...) får rette fejlen. Samtidig er min egen fejl, som dael fandt, blevet rettet. Løsningen er ikke elegant, men den virker. :o)
Option Explicit function skudaar(aar) dim nr skudaar=True on error resume next nr=DatePart("ww","29-02-" & aar,vbMonday,vbFirstFourDays) if err.number>0 then skudaar=False end function
Function WOY (MyDate)' Week Of Year WOY = DatePart("WW",MyDate,vbMonday, vbFirstFourDays) If WOY > 52 Then If DatePart("WW",DateAdd("d",7,MyDate), vbMonday, vbFirstFourDays) = 2 Then WOY = 1 End If End Function
function Ugenumre(maaned,aar) dim dage(12), min, max, i, t, ekstra dage(1)=31:dage(2)=28:dage(3)=31: dage(4)=30:dage(5)=31:dage(6)=30: dage(7)=31:dage(8)=31:dage(9)=30: dage(10)=31:dage(11)=30:dage(12)=31: if skudaar(aar) then dage(2)=29
min=WOY("01-" & maaned & "-" & aar) max=WOY(dage(maaned) & "-" & maaned & "-" & aar) if maaned=1 and min<>1 then t=min & "," min=1 end if if maaned=12 and max=1 then ekstra="1" max=52 end if for i=min to max t=t & i & "," next ugenumre=t & ekstra end function
'Testudskrifter i en VBscript version. 'Skal fjernes i en ASP-version: msgbox ugenumre(1,2003) msgbox ugenumre(2,2003) msgbox ugenumre(12,2003) msgbox ugenumre(1,2004) msgbox ugenumre(2,2004) msgbox ugenumre(12,2004) msgbox ugenumre(1,2005) msgbox ugenumre(2,2005) msgbox ugenumre(12,2005)
oki ... her er så også min nye version :-) Den skulle tage højde for at første uge i et år kan være en del af uge 52. Det er jo lidt kedeligt at ikke DatePart har denne lille bug, men det er jo ikke så svært at kode sig udenom denne.
Function getWeekNumbers( intMonth, intYear ) Dim strWeeks : strWeeks = "" Dim objStartDate : objStartDate = DateSerial( intYear, intMonth, "1" ) Dim objEndDate : objEndDate = DateAdd( "d", 27, objStartDate ) Dim intLastDay ' Finder sidste dag i måneden do until Month( objEndDate ) <> Month( objStartDate ) intLastDay = Day( objEndDate ) objEndDate = DateAdd( "d", 1, objEndDate ) Loop ' Tjekker om det er første måned for at tage med sidste uge fra foregående år if( Month( objStartDate ) = 1 ) then Dim objLastYearDate : objLastYearDate = objStartDate While WeekDay( objLastYearDate ) > 1 objLastYearDate = DateAdd( "d", -1, objLastYearDate ) Wend strWeeks = strWeeks & DatePart( "ww", objLastYearDate, vbMonday ) & ", " end if ' Finder ugenumre objEndDate = DateSerial( intYear, intMonth, intLastDay ) for i = DatePart( "ww", objStartDate, vbMonday ) To DatePart( "ww", objEndDate, vbMonday ) if( i > DatePart( "ww", objStartDate, vbMonday ) ) then strWeeks = strWeeks & ", " end if if( i = 53 ) then strWeeks = strWeeks & 1 else strWeeks = strWeeks & i end if next getWeekNumbers = strWeeks End Function
nmh >> nu kan det jo godt være at det er mine tømmermænd der driller lidt, men jeg kan ikke få dit script til at fungere ordentlig. jeg har kopieret din sidste posting, og den resulterer i noget der ikke helt er meningen, vil jeg tro :o] Jeg får resultaterne:
for uge 2 i 2005 returnerer den intet ?? :| det er lidt underlig, og jeg kan ikke helt se hvorfor. Principielt skulle det jo fungere. Hvorfor den returnerer alle uger i et år, frem til den uge du forespørger, er jo en anden sag :-)
Nu bliver det mystisk. Jeg har lige taget scriptet ned igen og kørt det (en eksakt kopi af det jeg lagde i mit forrige indlæg). Jeg får de helt rigtige værdier, som svarer til de kalendere, jeg kan kontrollere med:
Det er ubegribeligt, at mit script ikke virker hos dig. Jeg kører det på en windows xp pro maskine som et VBscript. Den er opdateret med alt (servicepacks etc.)
hmm... det jo lidt underlig ... jeg kører scriptet på en asp side ... men det burde jo ikke ha noget at sige :-| har du testet om mit script kører tilsvarende mærkelig hos dig ?
spørgsmålet er så ... er der nogle gange 53 uger i et år ??? jeg er sgu usikker. mener jeg har hørt om det gang, men jeg må indrømme at jeg ikke opererer på uger i mit daglige liv - jeg kigger blot på min køkken kalender hvis jeg har behov for at vide hvilken uge jeg skal have ferie :-)
Jeg var godt klar over, at der måske ville kunne komme problemer med dato-formatet, men da det hos mig virkede problemfrit regnede jeg med dato-funktionerne selv kunne konvertere. Men så har jeg nu lært, at der kan være forskelle på VBscript og VBscript på en server. Jeg vil prøve at lægge det på en asp-server lidt senere. Resultaterne, som vi nu begge får, svarer til mine kalendere. Jeg kan heller ikke fordrage ugenumre, og mener der altid bør være en dato (og helst også en ugedag med).
Jeg kører dit script om senere i dag. Det er da utroligt, at dette enkle problem, kan være så bøvlet.
Jo, dit script køre uden problemer som et alm. VBscript, men giver altså endnu ikke de rigtige ugenumre. Der er noget "pilleri" tilbage med de akavede numre i begyndelsen og slutningen af året. I år begynder uge 53 den mandag den 27.12.2004. ;o)
VBscript på min egen maskine er indstillet til dansk datoformat. Men en del asp servere forventer amerikansk dato format. 01-12-2003 blev opfattet som den 12. januar af asp-serveren. Defor gik det galt i december måned, og alle ugenumre blev udskrevet. DateSerial tager højde for det.
Disse dato-problemer har vist skabt mange grå hår i tidens løb. :o(
Datoer er noget lort ... det er meget ofte man rænder ind i de samme spørgsmål om datoer og formatteringer af disse. De er enhver udviklers lille marerit. Men jeg har lært mig at man ikke skal overlade for meget til maskinen ... den er sgu en dum sag på bunden :-) Man skal hele tiden stå over den med en rettet pegefinger for at passe på at den gør tingene helt som den skal ... hvis den ikke gør det, så er det frem med spanskrøret ... *smæk*!!
jeg er stadig "uenig" med modellen du har valgt som løsning, selv om den pt er den eneste der fungerer sobert og "by the book" :-D ( efter den sidste ændring ) Jeg kommer ikke til at opgive at min funktion vil fungere, da jeg mener at det er lidt overkill at kode på noget som systemet allerede ved. Du skriver også selv at du nok ikke er den "mest stolte far" angående din egen løsning, men man kan jo også diskutere hvor elegang noget kan blive når man er nødt til at kode ovenpå en bug. Det har hvertfald blevet en interessant debat af dette, og jeg har da også lært nogle ting om datoer jeg ikke vidste :-) tak for det ...
Det er diskusioner af den type, vi her har haft, der gør det sjovt at besvare spørgsmål på Eksperten. Jeg lært meget om datoproblematikken af dette. Jeg vil glæde mig til at se de sidste rettelser i din løsning. Kan du lade være med at lave dem? :o) Det er jo problemet i denne branche, at det tit er svært at helme, før man er rigtig tilfreds med sit "barn".
nmh >> så skulle den være der. nu returnerer min funktion nøjagtig det samme som din :]
Function getWeekNumbers( intMonth, intYear ) Dim strWeeks : strWeeks = "" Dim objStartDate : objStartDate = DateSerial( intYear, intMonth, "1" ) Dim objEndDate : objEndDate = DateAdd( "d", 27, objStartDate ) Dim intLastDay ' Finder sidste dag i måneden do until Month( objEndDate ) <> Month( objStartDate ) intLastDay = Day( objEndDate ) objEndDate = DateAdd( "d", 1, objEndDate ) Loop
' Tjekker om det er første måned for at tage med sidste uge fra foregående år if( Month( objStartDate ) = 1 ) then Dim objLastYearDate : objLastYearDate = objStartDate While WeekDay( objLastYearDate ) > 1 objLastYearDate = DateAdd( "d", -1, objLastYearDate ) Wend end if ' Finder ugenumre objEndDate = DateSerial( intYear, intMonth, intLastDay ) ' En tæller der bruges for at sætte komma i stringen der returneres ... ikke nødvendig, men det bliver en 'pæn' streng :o] Dim intCounter : intCounter = 0 while DatePart( "ww", objStartDate ) <> DatePart( "ww", objEndDate ) if( intCounter > 0 ) then strWeeks = strWeeks & "," end if strWeeks = strWeeks & DatePart( "ww", objStartDate, vbMonday, vbFirstFourDays ) objStartDate = DateAdd( "d", 7, objStartDate ) intCounter = intCounter + 1 wend ' Smider den sidste uge på strWeeks = strWeeks & "," & DatePart( "ww", objEndDate, vbMonday, vbFirstFourDays ) ' Returnerer resultat getWeekNumbers = strWeeks End Function
Men du har jo brugt DatePart, og den fejler som sagt af og til. Det gik godt for mine test data, men fejlen kommer frem, hvis du prøver følgende: getweekNumbers(12,2007) getweekNumbers(12,2035) getweekNumbers(12,2063) getweekNumbers(12,2091) getweekNumbers(12,2131) Det resulterer i, at alle ugenumre udskrives. Jeg tror ikke, der er andet at gøre end at benytte fejlretningsfunktionen WOY(...). :o(
Kender du i øvrigt en fiks metode til at afgøre om et år er et skudår? Jeg er ikke glad for den måde jeg gjorde det på.
argh !! pis !! :-D du har nok ret i det ... hvis jeg knalder WOY ind, *så* bliver jeg nok glad for min løsning :-)
Definitionen på et skudår skidseres sådan (hvertfald efter de definitioner på skudår jeg har fundet frem til):
Function isLeapYear( intYear ) Dim bIsLeapYear : bIsLeapYear = false ' hvis året er likt delelig med 400, så er det et skudår if( intYear mod 400 = 0 ) then bIsLeapYear = true else ' hvis året er likt delelig med 100, men ikke med 400, så er det ikke skudår if( intYear mod 100 = 0 AND intYear mod 400 <> 0 ) Then bIsLeapYear = false end if ' hvis året er likt delelig med 4, men ikke med 100, så er det skudår if( intYear mod 4 = 0 AND intYear mod 100 <> 0 ) then bIsLeapYear = true end if end if ' Det er vel en smart mand der kan forklare denne ??? if( intYear = 3600 ) then bIsLeapYear = false end if isLeapYear = bIsLeapYear End Function
Det kan selvfølgelig laves i nogle if'er mindre, men jeg har sat dem op sådan at hver regel er tydelig :-)
Skudår: Ja, det, du laver her, er lige efter definitionen, men jeg mente mere, om der var en af datofunktionerne, man kunne bruge til at afgøre det på en naturlig måde. Det, jeg lavede med at spørge efter datoen 29.02 og så checke om der var fejl, er ikke så tilfedsstillende, men det er simpelt.
jeg mener faktisk ikke vbscript har denne funktion indbygget. Jeg har tidligere haft behov for den, og kender til en tilsvarende funktion eksisterer i Java, og blev derfor irriteret over det ikke var en i VBscript ... (( med mindre jeg husker den forkerte ting jeg blev irriteret over :-] ))
Tak for dette link. Det fik mig til at lave skudårsfunktionen om, så den nu er "mere normal", og den er blevet ganske kort (så kort, at der egentlig ikke er grund til at arbejde med en særlig funktion).
Her er så min endelige version af funktionerne (det er snart blevet den uendelige historie):
function skudaar(aar) skudaar= (Day(DateSerial(aar,2,29))=29) end function
Function WOY (MyDate)' Week Of Year WOY = DatePart("WW",MyDate,vbMonday, vbFirstFourDays) If WOY > 52 Then If DatePart("WW",DateAdd("d",7,MyDate), vbMonday, vbFirstFourDays) = 2 Then WOY = 1 End If End Function
function Ugenumre(maaned,aar) dim dage, min, max, i, t, ekstra dage=array(0,31,28,31,30,31,30,31,31,30,31,30,31) if skudaar(aar) then dage(2)=29 min=WOY( DateSerial(aar, maaned, "01") ) max=WOY( DateSerial(aar, maaned, dage(maaned) ) ) if maaned=1 and min<>1 then t=min & "," min=1 end if if maaned=12 and max=1 then ekstra="1" max=52 end if for i=min to max t=t & i & "," next t= t & ekstra if mid(t,len(t))="," then t=left(t,len(t)-1) ugenumre=t end function
jeg er ikke sikker på om jeg kan lide den måde de tester på om et år er skudår eller ikke ... men den fungerer jo, så det kan vel ikke være noget galt ved den :-) Den virker bare "lidt for simpel" ... hmm ... :-D
håper nu hvertfald at dael har fulgt med i sin egen tråd, så han har fået med sig de sidste ændringer i dit forslag :)
Jeg siger tak til jer begge, for jeres ihærdig og gode svar. Og har fuldt spændt med i jeres kommentar/forslag.
Mvh
DAEL
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.