Jak uzyskać numer tygodnia w PascalScript?

0

Witam

Niestety w obecnym środowisku nie mam funkcji WeekOfTheYear.

Czy któryś z forumowiczów ma kod jak tą funkcję uzyskać?

Dziękuje

0

Potrzebuję kodu do PascalScript , to pierwsze podejdzie?

0
m4s napisał(a):

Potrzebuję kodu do PascalScript , to pierwsze podejdzie?

Musisz zaimplementować. Ew. czekać na kogoś kto zna PascalScript.

0

@m4s: kolega @vpiotr podał Ci link do implementacji w C++, więc bez problemu możesz sobie sam napisać taki kod w PascalScript. Nie ma w tym przykładzie żadnych skomplikowanych konstrukcji, stąd nie powinieneś mieć z tym żadnego problemu.

1

Przeportowałem kod z tego artykułu na Free Pascala i zdaje się działać prawidłowo – przynajmniej dla podanej w artykule przykładowej daty. Trzeba by sprawdzić działanie na konkretnym zbiorze danych wejściowych, aby mieć pewność co do poprawności wyników.


Jest kilka różnic, jesli o implementację chodzi:

  • część warunków można było skrócić za pomocą prostych operacji arytmetycznych – wykorzystałem Ord,
  • operator warunkowy zaimplementowałem w postaci funkcji IfThen z modułu Math,
  • do porównywania dat skorzystałem z funkcji CompareValue z modułu Math,
  • część zmiennych i instrukcji nie była potrzebna, więc je usunąłem.

Zestaw typów danych i funkcji:

{$MODE OBJFPC}{$LONGSTRINGS ON}{$MODESWITCH ADVANCEDRECORDS}

uses
  Math;

type
  TDayOfWeek = (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday);

type
  TDate = record
  public
    Year: Integer;
    Month: Integer;
    Day: Integer;
  public
    constructor Create(AYear, AMonth, ADay: Integer);
  end;

  constructor TDate.Create(AYear, AMonth, ADay: Integer);
  begin
    Year := AYear;
    Month := AMonth;
    Day := ADay;
  end;

  function IsLeapYear(AYear: Integer): Boolean;
  begin
    Result := (AYear mod 4 = 0) and ((AYear mod 100 <> 0) or (AYear mod 400 = 0));
  end;

  function DaysInMonth(AYear, AMonth: Integer): Integer;
  begin
    if AMonth = 2 then
      Result := 28 + Ord(IsLeapYear(AYear))
    else
      Result := 30 + Ord(AMonth in [4, 6, 9, 11]);
  end;

  function DateToDays(ADate: TDate): Integer;
  begin
    Result := ADate.Year * 365 + Ord(IsLeapYear(ADate.Year)) + DaysInMonth(ADate.Year, ADate.Month) + ADate.Day;
  end;

  function CompareDate(ADateA, ADateB: TDate): TValueRelationship;
  begin
    Result := Math.CompareValue(DateToDays(ADateA), DateToDays(ADateB));
  end;

  function GetDayOfWeek(AYear, AMonth, ADay: Integer): TDayOfWeek;
  const
    MONTH_TABLE: array [0 .. 11] of Integer = (0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4);
  var
    Year, Day: Integer;
  begin
    Year := AYear - Ord(AMonth < 3);
    Day := (Year + Year div 4 - Year div 100 + Year div 400 + MONTH_TABLE[AMonth - 1] + ADay) mod 7;

    Result := TDayOfWeek(Day);
  end;

  function GetISODayOfWeek(AYear, AMonth, ADay: Integer): Integer;
  begin
    Result := Ord(GetDayOfWeek(AYear, AMonth, ADay));
    Result += Ord(Result = 0) * 7;
  end;

  function GetWeekOne(AYear: Integer): TDate;
  var
    ISODay, ExtraDays: Integer;
  begin
    Result := TDate.Create(AYear, 1, 4);

    ISODay := GetISODayOfWeek(AYear, 1, 4);
    ExtraDays := 1 - ISODay;

    if ExtraDays < 0 then
    begin
      ExtraDays := -ExtraDays;

      Result.Year -= Ord(ExtraDays > 4);
      Result.Month := IfThen(ExtraDays > 4, 12, 1);
      Result.Day := IfThen(ExtraDays > 4, 31 - (ExtraDays - 4), Result.Day - (ExtraDays - 4));
    end
    else
      Result.Day += ExtraDays;
  end;

  function GetWeekOfYear(ADate: TDate): Integer;
  var
    WeekOne: TDate;
  begin
    if CompareDate(ADate, TDate.Create(ADate.Year, 12, 29)) <> LessThanValue then
    begin
      WeekOne := GetWeekOne(ADate.Year + 1);

      if CompareDate(ADate, WeekOne) = LessThanValue then
        WeekOne := GetWeekOne(ADate.Year)
    end
    else
    begin
      WeekOne := GetWeekOne(ADate.Year);

      if CompareDate(ADate, WeekOne) = LessThanValue then
        WeekOne := GetWeekOne(ADate.Year - 1)
    end;

    Result := (DateToDays(ADate) - DateToDays(WeekOne)) div 7 + 1;
  end;

Oraz przykład wywołania:

Write('Week number: ', GetWeekOfYear(TDate.Create(2015, 12, 5)));

Niestety ScriptPascal jest mi obcy – nigdy go nie używałem, nie wiem na co konkretnie ten dialekt pozwala i co zawiera jego biblioteka standardowa. Dlatego też traktuj ten kod jako podstawę i jeśli nie da się tego kodu bezpośrednio użyć w Twoim projekcie to pomyślimy nad jego przystosowaniem do używanego przez Ciebie dialektu.

0

Dzięki za poświęcony czas i chęci.

Próbowałem wkleić ten kod ale bolało go brak ;

W załączniku obrazek z listą funkcji czasu do wykorzystania w moim środowisku

3

Programowanie nie polega na przeklejaniu przykładów z internetów. Musisz czasem sam coś napisać...

1

@m4s: jeśli datę reprezentuje wbudowany typ TDate lub TDateTime, który standardowo jest po prostu liczbą zmiennoprzecinkową typu Double, to cały mój kod musisz zmodyfikować. Kod który podałem korzysta z rekordu do opisu daty, w którym rok, miesiąc i dzień są osobnymi liczbami całkowitymi.

Aby to zrobić, wystarczy po prostu usunąć ten typ TDate (ten rekord), zamienić go na wbudowany typ do przechowywania dat, a następnie wszystkie funkcje zmodyfikować. Najpierw wyciągnąć numer roku, miesiąca i dnia z daty za pomocą funkcji DecodeDate (lub YearOf, MonthOf i DayOf jeśli potrzeba jendego-dwóch składowych) i wtedy uzyskane wartości wykorzystać do obliczeń. Jeśli funkcja ma zwracać TDate to na koniec należy użyć funkcji EncodeDate.

5 minut roboty.

1 użytkowników online, w tym zalogowanych: 0, gości: 1