Witam
Niestety w obecnym środowisku nie mam funkcji WeekOfTheYear
.
Czy któryś z forumowiczów ma kod jak tą funkcję uzyskać?
Dziękuje
m4s napisał(a):
Potrzebuję kodu do PascalScript , to pierwsze podejdzie?
Musisz zaimplementować. Ew. czekać na kogoś kto zna PascalScript.
@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.
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:
Ord
,IfThen
z modułu Math
,CompareValue
z modułu Math
,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.
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
Programowanie nie polega na przeklejaniu przykładów z internetów. Musisz czasem sam coś napisać...
@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.