Avatar billede athlon-pascal Juniormester
07. oktober 2003 - 08:37 Der er 6 kommentarer og
1 løsning

Find og ret fejl i dato-procedure

Jeg har lavet min egen EncodeDate-procedure, dels for sjovt, men også med henblik på senere understøttelse af den julianske kalender, og ikke mindst det danske kalenderskift d. 1/3 1700, der kom eftet 18/2 1700, i et program jeg er ved at lave.
Problemet er bare, at proceduren har en fejl. Fejlen findes ved d. 1/1 og d. 1/2 i skudår, det giver samme dag. Det påvirker resten af året, da det bliver skubbet med en dag, hvilket ikke er så hensigtsmæssigt.

Det jeg ønsker er, at du kan finde og rette fejlen.

Jeg bruger Delphi 7 Personal under Windows XP.

På forhånd tak :-)

function ExtMod(a, b: Extended): Extended;
begin
  Result := Trunc(a - Trunc(a / b) * b);
end;

function DaysInMonthEx(Month: Word; Year: Integer): Word;
const
  NormYear: array [1..12] of Word =
    (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  LeapYear: array [1..12] of Word =
    (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  Year1700: array [1..12] of Word =
    (31, 18, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);   
begin
  if not (Month in [1..12]) then
    Result := 0
//  else if Year = 1700 then
//    Result := Year1700[Month]
  else if (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0)) then
    Result := LeapYear[Month]
  else
    Result := NormYear[Month];
end;

function CountFromStartOfYear(Month: Word; Year: Integer): Integer;
const
  Count: Array [1..12] of Integer =
    (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
begin
  if not (Month in [1..12]) then
    Result := 0
  else if (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0))
  and (Month > 2) then
    Result := Count[Month] + 1
  else
    Result := Count[Month];
end;

procedure DecodeDateHest(Date: TDate; var Y: Integer; var M, D: Word);
const
  DaysInYear = 365;
  DaysIn4Years = DaysInYear * 4 + 1;
  DaysIn100Years = 36524;
  DaysIn400Years = 146097;
var
  xDate, xY: Extended;
begin
  xDate := Date + 693593 + 365; // "Nulstil" dato, nemmere at arbejde med :-)

  xY := (xDate - ExtMod(xDate, DaysIn400Years)) / DaysIn400Years * 400;
  xDate := ExtMod(xDate, DaysIn400Years);
  xY := xY + (xDate - ExtMod(xDate, DaysIn100Years)) / DaysIn100Years * 100;
  xDate := ExtMod(xDate, DaysIn100Years);
  xY := xY + (xDate - ExtMod(xDate, DaysIn4Years)) / DaysIn4Years * 4;
  xDate := ExtMod(xDate, DaysIn4Years);
  xY := xY + (xDate - ExtMod(xDate, DaysInYear)) / DaysInYear;
  xDate := ExtMod(xDate, DaysInYear);
  Y := Trunc(xY);

  M := 1;

  while (Trunc(xDate) - CountFromStartOfYear(M, Y) + 1 > DaysInMonthEx(M, Y))
  and (M < 12) do
    Inc(M);

  D := Trunc(xDate) - CountFromStartOfYear(M, Y) + 1
end;
Avatar billede athlon-pascal Juniormester
07. oktober 2003 - 08:38 #1
Det er min egen DecodeDate-procedure jeg har lavet, og gerne vil have rettet :-)
Avatar billede athlon-pascal Juniormester
07. oktober 2003 - 13:54 #2
Hmm... jeg kan hæve pointsummen..?
Avatar billede Slettet bruger
07. oktober 2003 - 14:29 #3
Kan du ik bare gøre sådan:

  ...
  if (Y mod 4) = 0 then
  D := Trunc(xDate) - CountFromStartOfYear(M, Y) + 2
  else
  D := Trunc(xDate) - CountFromStartOfYear(M, Y) + 1
end;
Avatar billede athlon-pascal Juniormester
07. oktober 2003 - 14:38 #4
hejhej -> Nej, det kan man ikke bare :-(
Trunc(xDate) - CountFromStartOfYear(M, Y) vil med 1/1 og 2/1 give det samme, når det er skudår :-(
Avatar billede athlon-pascal Juniormester
07. oktober 2003 - 14:42 #5
I øvrigt finder man ikke skudår ved at sige:
  if Y mod 4 = 0 then
Det er kun i den julianske kalender man gør det.

I den gregorianske, som vi har brugt i Danmark siden 1/3 1700, hedder det:
if (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0)) then

Læs evt. http://da.wikipedia.org/wiki/Gregorianske_kalender :-)
Avatar billede athlon-pascal Juniormester
07. oktober 2003 - 15:16 #6
Fejlen opstår vist i eller før disse linjer:

  xY := xY + (xDate - ExtMod(xDate, DaysIn100Years)) / DaysIn100Years * 100;
  xDate := ExtMod(xDate, DaysIn100Years);
Avatar billede athlon-pascal Juniormester
19. oktober 2003 - 20:23 #7
Jeg lukker :-(
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester