View Full Version : آموزش: توابع تبدیل تاریخ با دقت 5000 سال تست شده با تقویم رسمی ایران http://www.time.ir
یوسف زالی
سه شنبه 17 اردیبهشت 1392, 18:17 عصر
سلام.
دیدم هنوز برنامه نویسا دنبال این داستان هستند و دیدم که هنوز با تاریخ های کبیسه مشکل دارند.
یک بار برای همیشه قال قضیه رو بکنیم، نه؟!
برای همین این توابع رو برای دوستان آماده کردم.
باشد که با دعای خود موجبات آرامش رفتگان و آسایش ماندگان باشند.
اول از همه این رو در یک یونیت بگذارید:
const
SolarDayOfWeek: array [0..6] of string = ('شنيه',
'يک شنبه',
'دوشنبه',
'سه شنبه',
'چهارشنبه',
'پنج شنبه',
'جمعه');
GregorianDayOfWeek: array [0..6] of string = ('Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday');
INVALID_SOLAR_DATE = '1300/01/01';
INVALID_GREGORIAN_DATE = '1921/03/21';
var
FormatSetting: TFormatSettings;
type
TDateBase = (dbSolar, dbGregorian);
function JalCal(JY: Integer; var GY: Integer; var March: integer): boolean;
const
breaks: Array[1..20] of Integer = (-61, 9, 38, 199, 426, 686, 756, 818,
1111, 1181, 1210, 1635, 2060, 2097,
2192, 2262, 2324, 2394, 2456, 3178);
var
leapJ, jp, jm, jump, N: Integer;
j: Integer;
leap, leapG: Integer;
begin
GY := JY +621;
leapJ := -14;
jp := breaks[1];
if (JY < jp) or (JY >= breaks[20]) then
begin
writeln('error');
exit;
end;
for j := 2 to 20 do
begin
jm := breaks[j];
jump := jm -jp;
if Jy < jm then
Break;
leapJ := leapJ +jump div 33 * 8 +(jump mod 33) div 4;
jp := jm;
end;
N := Jy -jp;
leapJ := leapJ +N div 33 * 8 +((N mod 33) +3) div 4;
if(jump mod 33 = 4) and (jump -N = 4)then
leapJ := leapJ +1;
leapG := Gy div 4 -(Gy div 100 +1) * 3 div 4 -150;
March := 20 +leapJ -leapG;
if (jump -N < 6) then
N := N -jump +(jump +4) div 33 * 33;
leap := ((N +1) mod 33 -1) mod 4;
if leap = -1 then
leap := 4;
Result := leap = 0;
end;
initialization
GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, FormatSetting);
FormatSetting.ShortTimeFormat := 'HH:MM:SS';
FormatSetting.ShortDateFormat := 'YYYY/MM/DD';
// FormatSetting.DecimalSeparator := DECIMAL_DELIMITER;//
// FormatSetting.ThousandSeparator := THOUSAND_DELIMITER;//
-------------------------------------------------------------------------------------------------------
تبدیل تاریخ شمسی به میلادی:
function Date_SolarToGregorian(SolarDate: string; CanZero: boolean = false): string;
var
SYear, SMonth, SDay: integer;
GYear, GMonth, GDay: integer;
SIsLeap, GIsLeap: boolean;
GDate: TDate;
begin
if CanZero and Date_IsZeroValidDate(SolarDate, dbSolar) then
begin
Result := '0000/00/00';
Exit;
end;
if (SolarDate <= INVALID_SOLAR_DATE) or (SolarDate > '3000/12/30') or (length(SolarDate) <> 10) then
begin
Result := INVALID_GREGORIAN_DATE;
// MessageBeep(0);
exit;
end;
if not Date_IsValidDate(SolarDate, dbSolar) then
begin
Result := INVALID_GREGORIAN_DATE;
// MessageBeep(0);
exit;
end;
SYear := StrToInt(Copy(SolarDate, 1, 4));
SMonth := StrToInt(Copy(SolarDate, 6, 2));
SDay := StrToInt(Copy(SolarDate, 9, 2));
SIsLeap := JalCal(SYear, GYear, GDay);
GMonth := 3;
GIsLeap := SysUtils.IsLeapYear(GYear);
GDate := StrToDate(RightStr('000' + IntToStr(GYear), 4) + '/' + RightStr('0' + IntToStr(GMonth), 2) + '/' + RightStr('0' + IntToStr(GDay), 2), FormatSetting);
GDate := GDate +Date_DaysOfYear(SolarDate, dbSolar) -1;
Result := DateToStr(GDate, FormatSetting);
end;
تبدیل معکوس با استفاده از ریشه یابی باینری (اینجا (http://barnamenevis.org/showthread.php?388044-%D8%AF%D9%84%D9%81%DB%8C-%D9%88-%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C&p=1721046&viewfull=1#post1721046)) :
function MinimalMoveDateSolar(Dt: string; Step: integer): string;
var
SYear, SMonth, SDay: integer;
GYear, GDay: integer;
DPX: integer;
begin
SYear := StrToInt(Copy(Dt, 1, 4));
SMonth := StrToInt(Copy(Dt, 6, 2));
SDay := StrToInt(Copy(Dt, 9, 2));
repeat
DPX := Date_DaysPerYear(SYear, dbSolar);
if Step < DPX then
break;
dec(Step, DPX);
inc(SYear);
until false;
repeat
DPX := Date_DaysPerMonth(SYear, SMonth, dbSolar);
if Step < DPX then
break;
dec(Step, DPX);
inc(SMonth);
if SMonth > 12 then
begin
SMonth := 1;
inc(SYear);
end;
until false;
inc(SDay, Step);
if SDay > Date_DaysPerMonth(SYear, SMonth, dbSolar) then
begin
SDay := 1;
inc(SMonth);
if SMonth > 12 then
begin
SMonth := 1;
inc(SYear);
end;
end;
Result := RightStr('000' + IntToStr(SYear), 4) + '/' + RightStr('0' + IntToStr(SMonth), 2) + '/' + RightStr('0' + IntToStr(SDay), 2);
end;
function Date_GregorianToSolar(GregorianDate: string): string;
var
S, S1, S2: string;
G, G1, G2: string;
LoopCounter: integer;
begin
if (GregorianDate <= INVALID_GREGORIAN_DATE) or (GregorianDate > '3622/03/20') or (length(GregorianDate) <> 10) then
begin
Result := INVALID_SOLAR_DATE;
// MessageBeep(0);
exit;
end;
if not Date_IsValidDate(GregorianDate, dbGregorian) then
begin
Result := INVALID_SOLAR_DATE;
// MessageBeep(0);
exit;
end;
S1 := IntToStr(StrToInt(Copy(GregorianDate, 1, 4)) -622) + '/01/01';
S2 := IntToStr(StrToInt(Copy(GregorianDate, 1, 4)) -621) + '/12/29';
G1 := Date_SolarToGregorian(S1);
G2 := Date_SolarToGregorian(S2);
while G1 > GregorianDate do
begin
S1 := Date_MoveDate(S1, -100, dbSolar);
G1 := Date_SolarToGregorian(S1);
end;
while G2 < GregorianDate do
begin
S2 := Date_MoveDate(S2, 100, dbSolar);
G2 := Date_SolarToGregorian(S2);
end;
LoopCounter := 0;
if G1 = GregorianDate then
Result := S1
else if G2 = GregorianDate then
Result := S2
else
begin
repeat
S := MinimalMoveDateSolar(S1, round(Date_DaysBetween(S1 ,S2, dbSolar) / 2));
G := Date_SolarToGregorian(S);
if G = GregorianDate then
begin
Result := S;
break;
end
else if G > GregorianDate then
S2 := S
else if G < GregorianDate then
S1 := S;
inc(LoopCounter);
until LoopCounter >= 13;
if LoopCounter >= 13 then
begin
Result := INVALID_GREGORIAN_DATE;
// MessageBeep(0);
end
else
Result := S;
end;
end;
توابع دیگر:
function Date_DaysOfYear(Dt: string; DateBase: TDateBase): integer;
var
SMonth, SDay: integer;
begin
if DateBase = dbSolar then
begin
SMonth := StrToInt(Copy(Dt, 6, 2));
SDay := StrToInt(Copy(Dt, 9, 2));
case SMonth of
1: Result := SDay;
2: Result := SDay +31;
3: Result := SDay +62;
4: Result := SDay +93;
5: Result := SDay +124;
6: Result := SDay +155;
7: Result := SDay +186;
8: Result := SDay +216;
9: Result := SDay +246;
10: Result := SDay +276;
11: Result := SDay +306;
12: Result := SDay +336;
end;
end
else
Result := DayOfTheYear(StrToDate(Dt, FormatSetting));
end;
function Date_DaysPerYear(Y: integer; DateBase: TDateBase): integer;
begin
Result := DaysPerYear[Date_IsLeapYear(Y, DateBase)];
end;
function Date_DaysPerMonth(Y, M: integer; DateBase: TDateBase): integer;
begin
if DateBase = dbSolar then
case M of
1..6: Result := 31;
7..11: Result := 30;
12: Result := IfThen(Date_IsLeapYear(Y, dbSolar), 30, 29);
end
else
Result := MonthDays[(M = 2) and SysUtils.IsLeapYear(Y), M];
end;
function Date_DaysBetween(Dt1, Dt2: string; DateBase: TDateBase): integer;
var
SYear1: integer;
SYear2: integer;
i, Day: integer;
X1, X2: integer;
begin
if DateBase = dbSolar then
begin
SYear1 := StrToInt(Copy(Dt1, 1, 4));
SYear2 := StrToInt(Copy(Dt2, 1, 4));
Day := 0;
for i := SYear1 +1 to SYear2 -1 do
Day := Day +Date_DaysPerYear(i, dbSolar);
X1 := Date_DaysOfYear(Dt1, dbSolar);
X2 := Date_DaysOfYear(Dt2, dbSolar);
Result := Day + X2 -X1 +IfThen(SYear1 = SYear2, 0, Date_DaysPerYear(SYear1, dbSolar));
end
else
Result := DaysBetween(StrToDate(Dt1, FormatSetting), StrToDate(Dt2, FormatSetting));
end;
function Date_IsLeapYear(Y: integer; DateBase: TDateBase): boolean;
var
DD, YY: integer;
begin
if DateBase = dbSolar then
Result := JalCal(Y, YY, DD)
else
Result := SysUtils.IsLeapYear(Y);
end;
function Date_MoveDate(Dt: string; Step: integer; DateBase: TDateBase): string;
var
D: TDate;
begin
if DateBase = dbSolar then
Dt := Date_SolarToGregorian(Dt);
D := StrToDate(Dt, FormatSetting) +Step;
Dt := DateToStr(D, FormatSetting);
if DateBase = dbSolar then
Dt := Date_GregorianToSolar(Dt);
Result := Dt;
end;
function Date_DifDate(Dt1, Dt2: string; DateBase: TDateBase): integer;
begin
if DateBase = dbSolar then
begin
Dt1 := Date_SolarToGregorian(Dt1);
Dt2 := Date_SolarToGregorian(Dt2);
end;
Result := DaysBetween(StrToDate(Dt1, FormatSetting), StrToDate(Dt2, FormatSetting));
end;
function Date_IsValidDate(Dt: string; DateBase: TDateBase): boolean;
var
DD, MM, YY: integer;
begin
if length(Dt) <> 10 then
begin
Result := false;
exit;
end;
DD := StrToInt(Copy(Dt, 9, 2));
MM := StrToInt(Copy(Dt, 6, 2));
YY := StrToInt(Copy(Dt, 1, 4));
if DateBase = dbSolar then
Result := (MM in [1..12])
and (
(MM in [1..6]) and (DD in [1..31]))
or
((MM in [7..11]) and (DD in [1..30]))
or
((MM = 12) and (DD in [1..IfThen(Date_IsLeapYear(YY, dbSolar), 30, 29)])
)
else
Result := IsValidDate(YY, MM, DD);
end;
function Date_IsZeroValidDate(Dt: string; DateBase: TDateBase): boolean;
var
DD, MM, YY: integer;
begin
if length(Dt) <> 10 then
begin
Result := false;
exit;
end;
DD := StrToInt(Copy(Dt, 9, 2));
MM := StrToInt(Copy(Dt, 6, 2));
YY := StrToInt(Copy(Dt, 1, 4));
if DateBase = dbSolar then
Result := ((DD = 0) and (MM in [0..12]))
or
((MM = 0) and (DD in [0..31]))
or
((YY = 0) and (DD in [0..31]) and (MM in [0..12]))
else
Result := false;
end;
function Date_FirstDayOfYear(Year: integer): string;
begin
result := IntToStr(Year) + '/01/01';
end;
function Date_LastDayOfYear(Year: integer; DateBase: TDateBase): string;
begin
if Date_IsLeapYear(Year, DateBase) then
Result := IntToStr(Year) + '/12/30'
else
Result := IntToStr(Year) + '/12/29';
end;
function Date_CurrentDate(DateBase: TDateBase = dbSolar): string;
begin
if DateBase = dbSolar then
Result := Date_GregorianToSolar(DateToStr(Date, FormatSetting))
else
Result := DateToStr(Date, FormatSetting);
end;
function Date_DateToString(Dt: TDateTime; DateBase: TDateBase): string;
begin
if DateBase = dbSolar then
Result := Date_GregorianToSolar(DateToStr(Dt, FormatSetting))
else
Result := DateToStr(Dt, FormatSetting);
end;
function Date_StringToDate(Dt: string; DateBase: TDateBase): TDateTime;
begin
if DateBase = dbSolar then
Result := StrToDate(Date_SolarToGregorian(Dt), FormatSetting)
else
Result := StrToDate(Dt, FormatSetting);
end;
دوستان من این توابع رو از یونیتی که نوشته بودم و 12000 خط داره کپی کردم. ممکنه بعضی جاهاش رو یادم رفته باشه.
اگر جایی ارور داد بگید تا بگذارم.
امیدوارم که دوستان یادگاری از من داشته باشند.
موفق باشید.
fahimi
جمعه 17 خرداد 1392, 06:42 صبح
سلام
کدام یک از تابع بالا تاریخ شمسی را برمی گرداند
fahimi
جمعه 17 خرداد 1392, 07:00 صبح
پیدا کردم Date_GregorianToSolar
در ضمن پست بالا بصورت یونیت ضمیمه نمودم
kamran749
سه شنبه 04 تیر 1392, 10:21 صبح
پیدا کردم Date_GregorianToSolar
در ضمن پست بالا بصورت یونیت ضمیمه نمودم
با سلام و تشکر
لطفا طريقه فراخواني هر کدام از تاريخها را بر روي کپشن يک ليبل بنويسيد.
ممنون:تشویق:
یوسف زالی
سه شنبه 04 تیر 1392, 11:19 صبح
فایل یونیت یکمی اصلاح شد.
طریقه فراخوانیش خیلی ساده هست. شما کجاش مشکل داری؟ بگو توضیح بدم.
kamran749
پنج شنبه 06 تیر 1392, 11:31 صبح
فایل یونیت یکمی اصلاح شد.
طریقه فراخوانیش خیلی ساده هست. شما کجاش مشکل داری؟ بگو توضیح بدم.
سلام
طريقه فراخواني تاريخ شمسي(Date_GregorianToSolar) را پيدا نمودم، اما بقيه توابع را نمي دانم چه هستند و چگونه فراخواني ميشوند.منجمله اگر بخواهيم تاريخ شمسي به صورت حروف باشد ، بايد چه تابعي را فراخواني کنيم يا تاريخ قمري ...؟:متعجب:
یوسف زالی
پنج شنبه 06 تیر 1392, 13:09 عصر
ما همین جوریش هم باید بشینیم تا ببینیم ماه رو دیدن یا نه تا روزه بگیریم یا نه،
هیچ تاریخ قمری ای دقیق نیست. تنها باید گذشته اون رو در دیتابیس گشت.
در خصوص فارسی شدن، این توابع رو اضافه کنید:
function Date_SolarMonthName(Month: integer): string;
begin
case Month of
1: Result := 'فروردین';
2: Result := 'اردیبهشت';
3: Result := 'خرداد';
4: Result := 'تیر';
5: Result := 'مرداد';
6: Result := 'شهریور';
7: Result := 'مهر';
8: Result := 'آبان';
9: Result := 'آذر';
10: Result := 'دی';
11: Result := 'بهمن';
12: Result := 'اسفند';
end;
end;
function Date_SolarFullName(Dt: string): string;
var
YY, MM, DD: string;
begin
DD := Copy(Dt, 9, 2);
MM := Copy(Dt, 6, 2);
YY := Copy(Dt, 1, 4);
Result := DD + ' ' + Date_SolarMonthName(StrToInt(MM)) + ' ' + YY;
end;
مهم بیس داستانه، بقیش به راحتی توسعه پذیره.
kamran749
چهارشنبه 12 تیر 1392, 06:39 صبح
ما همین جوریش هم باید بشینیم تا ببینیم ماه رو دیدن یا نه تا روزه بگیریم یا نه،
هیچ تاریخ قمری ای دقیق نیست. تنها باید گذشته اون رو در دیتابیس گشت.
در خصوص فارسی شدن، این توابع رو اضافه کنید:
function Date_SolarMonthName(Month: integer): string;
begin
case Month of
1: Result := 'فروردین';
2: Result := 'اردیبهشت';
3: Result := 'خرداد';
4: Result := 'تیر';
5: Result := 'مرداد';
6: Result := 'شهریور';
7: Result := 'مهر';
8: Result := 'آبان';
9: Result := 'آذر';
10: Result := 'دی';
11: Result := 'بهمن';
12: Result := 'اسفند';
end;
end;
function Date_SolarFullName(Dt: string): string;
var
YY, MM, DD: string;
begin
DD := Copy(Dt, 9, 2);
MM := Copy(Dt, 6, 2);
YY := Copy(Dt, 1, 4);
Result := DD + ' ' + Date_SolarMonthName(StrToInt(MM)) + ' ' + YY;
end;
مهم بیس داستانه، بقیش به راحتی توسعه پذیره.
سلام دوست عزيز
به فکر ما مبتدي ها هم باش.من اين کد را کجا بگذارم و چگونه آنرا فراخواني کنم تا تاريخ شمسي را به صورت حروف به من برگرداند.:متعجب: من مي خواهم تاريخ اينگونه نوشته شود.
براي مثال: بيست و پنجم ، خرداد ، هزار و سيصد و نود و دو
يا مثلا: بيست و پنجم ، خرداد ، 1392
قبلا چندين بار در جاهاي مختلف درخواست کردم ولي همه به اين طرف و آن طرف پاس داده اند و به غير از يک کد که با سالهاي کبيسه مشکل دارد ، چيزي گيرم نيامد.
SayeyeZohor
پنج شنبه 13 تیر 1392, 23:28 عصر
ShowMessage(Date_SolarFullName('1392/02/02'));
eshge89
شنبه 22 تیر 1392, 15:06 عصر
سلام دوست عزيز خوبي؟
ممنونم از توابعي كه گذاشتين
حالا مي شه بگين با كدوم يكي از اين توابع ميشه يك عدد را با تاريخ شمسي كم يا جمع كرد؟؟واضحتر توضيح بدين
يا در صورت امكان يه نمونه برنامه در اين خصوص بذارين
با تشكر
منتطرتون هستم
خيلي واجبه دوست عزيز
eshge89
دوشنبه 24 تیر 1392, 10:22 صبح
سلام مهندس - من همچنان منتظر پاسختون هستمYou-Seeمهندس (http://barnamenevis.org/member.php?70247-You-See) - ممنون مي شم سريعتر راهنماييم كنيد
یوسف زالی
دوشنبه 24 تیر 1392, 10:27 صبح
توابع بالا رو که بخونین همه چیز واضحه.
برای مثال افزودن یک عدد به تاریخ شمسی:
NewDate := Date_MoveDate('1392/04/25', 5, dbSolar);
eshge89
دوشنبه 24 تیر 1392, 11:55 صبح
مهندس من زياد با دلفي كار نكردم ميشه زحمت بكشيد و برام يه نمونه برنامه بدين ؟؟؟
نگاه كردم اما چيزي متوجه نشدم .
ميشه زودتر بدين ؟؟
یوسف زالی
دوشنبه 24 تیر 1392, 11:59 صبح
دوست عزیز شما شروع کن هر جا گیر کردی کمک می کنیم.
دستوری که گذاشتم به حدی واضحه که نیازی به توضیح نداره.
بسم الله.. استارت بزن سوال داشتی بپرس.
eshge89
سه شنبه 25 تیر 1392, 09:35 صبح
من تمام توابع رو تو قسمت كد نويسي فرمم اضافه كردم اما ارور داد
نتونستم استفاده كنم
ميشه لطف كنيد يه نمونه برنامه كوچولو در اختيارم بذاريد؟؟؟
خيلي لازم دارم
ELI994
چهارشنبه 26 تیر 1392, 09:36 صبح
با سلام و تشکر از زحماتی که کشیدین
من یونیتی رو که شما زحمتش رو کشیده بودین رو به پروژه ام اضافه کردم ولی این پیغام ها رو دریافت کردم
[C++ Error] AU.cpp(8): E2209 Unable to open include file 'U30DateUnit.hpp'
[C++ Error] AU.cpp(61): E2268 Call to undefined function 'Date_SolarFullName'
#pragma hdrstop
#include "AU.h"
#include "B.hpp"
#include "U30DateUnit.hpp"
با توجه با اینکه این یونیت هم به فرم اصلی اضافه شده
لطفا راهنمایی بفرمائید
یوسف زالی
چهارشنبه 26 تیر 1392, 09:44 صبح
سلام.
فکر می کنم که در قسمت Interface اعلان این تابع رو نگذاشتید.
اگر همچنان مشکل داشتید نمونه سورس رو ضمیمه کنید نگاه کنم.
eshge89
چهارشنبه 26 تیر 1392, 10:05 صبح
دوست عزيز من همچنان منتظر راهنمايي هاي شما هستم
ELI994
چهارشنبه 26 تیر 1392, 11:52 صبح
من تو بیلدر اینرو اضافه کردم
یوسف زالی
چهارشنبه 26 تیر 1392, 12:56 عصر
یکمی زحمت بدید به خودتون،
آقا/خانم عشق 89 :
شما نه می گی ارورت چیه نه اصلا کدی گذاشتی، این که نمی شه.
آقا/خانم الی 994 :
جواب شما که ارتباطی به حرف من نداشت. سورس نذاشتید!
به هر حال این نمونه برنامه کوچیک رو براتون می گذارم. امیدوارم راتون بندازه.
موفق باشید.
ELI994
چهارشنبه 26 تیر 1392, 13:30 عصر
من همیشه تو یه برنامه دیگه اول کدی رو که بلد نیستم رو تست می کنم بعد به برنامه اصلی اضافه می کنم
این هم فایل تست هستش
107399
ممنون از اینکه توجه فرمودین
فقط اگه امکانش باشه نحوه پیاده سازیش رو بهم بگین
یوسف زالی
چهارشنبه 26 تیر 1392, 13:55 عصر
عزیز من، گفتم که سورس بدید.
از طرفی نمونه برنامه هم گذاشتم.
با سی پلاس پلاس برنامه دادید واسه تست یونیت دلفی؟!
این فایلیه که توش ایناست:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM("D:\Example\AU.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
//---------------------------------------------------------------------------
من چی این رو باید ببینم؟
دوست عزیز شما مبانی برنامه نویسی رو فکر می کنم زیاد بلد نیستی، پیشنهاد من اینه که اول یک کتاب از مبانی پیدا کنی و چند تا برنامه کوچیک با دلفی بنویسی، بعد در خدمتیم.
موفق باشی.
ELI994
شنبه 29 تیر 1392, 08:06 صبح
من اولش هم بهتون گفتم که برنامه من توی سی بیلدر هستش.
آقا/خانم الی 994 :
جواب شما که ارتباطی به حرف من نداشت. سورس نذاشتید!
این جواب رو به من دادین . ماشالله مجال حرف زدن که به آدم نمیدین
من کمکی که ازتون خواستم این بود که یونیتتون تو سی بیلدر ارور میده همین بود جرمم
یوسف زالی
شنبه 29 تیر 1392, 09:14 صبح
در پست شماره 16 اشاره ای به این موضوع نشد.
در پست 19 هم گفتید در بیلدر اضافه کردم.
شما می تونید در نوت پد هم برنامه نویسی کنید. من که نمی دونم در بیلدر می شه دلفی کد زد و کامپایل کرد یا نه (تا جایی که یادمه می شه!)
بنابراین شما باید زبان مورد استفاده رو می گفتید.
برای این که از این توابع در زبان خودتون استفاده کنید باید یک نفر زحمت DLL کردن این توابع رو براتون بکشه.
موفق باشید.
BORHAN TEC
شنبه 29 تیر 1392, 16:38 عصر
سلام
برای این که از این توابع در زبان خودتون استفاده کنید باید یک نفر زحمت DLL کردن این توابع رو براتون بکشه.
نیازی به این کار نیست. C++ Builder توانایی Compile و استفاده از یونیت های دلفی را دارد. :کف: من یک پروژه نمونه را در C++ Builder ایجاد کرده ام که می تواند از یونیت U30DateUnit.pas استفاده کند. این پروژه نمونه با C++ Builder XE4 تست شده است که آنرا ضمیمه کرده ام. انجام این کار حتی در نسخ فسیل شده C++ Builder هم امکان پذیر است. در ضمن بنده قبلاً ویدئویی را در خصوص استفاده از یونیتهای دلفی در BCB ایجاد کرده ام که فیلم آن در آدرس زیر قرار دارد:
http://www.irstu.com/?p=8490
موفق باشید...
hector2000
پنج شنبه 17 مرداد 1392, 14:15 عصر
من این تابع را نوشتم که خیلی سریع و دقیق تاریخ میلادی را به شمسی تبدیل می کند
function MiladiToShamsi(N:tdate):string;
const
W : array[1..7] of widestring = ('یکشنبه','دوشنبه','سه شنبه','چهارشنبه','پنجشنبه','ج عه','شنبه');
Mon : array[1..12] of widestring = ('فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند');
var
days,Y,D,M:integer;
begin
days:= DaysBetween(N,EncodeDate(1900,1,1));
days :=days + 2112;
Y := 1273;
M := 0;
D := 0;
Y := Y + Trunc(days / 12053) * 33;
days := days mod 12053;
Y := Y + Trunc(days / 1461) * 4;
days := days mod 1461;
if (days = 1460)then
begin
Y := Y + 3;
days := 365;
end
else
begin
Y := Y + Trunc(days / 365);
days := days mod 365;
end;
if (days < 186)then
begin
M := Trunc(days / 31) + 1;
D := days mod 31 + 1;
end
else
begin
M := Trunc((days - 186) / 30) + 7;
D := (days - 186) mod 30 + 1;
end;
result:= inttostr(Y)+' ' + Mon[M] + ' ' + Inttostr(D)+ ' ' + W[DayOfWeek(N)];
end;
طریقه استفاده:
Label1.caption:=MiladiToShamsi(date);
یوسف زالی
پنج شنبه 17 مرداد 1392, 23:28 عصر
این قطعه کد در بازه زمانی کوتاه معقول به نظر می رسه.
بنا به دلایلی که در استفاده از کامپوننت شمسی میلادی استفاده کردم، اولین روز شمسی رو 01/01/1300 قرار دادم.
از همین تاریخ شروع می کنیم به مقایسه:
2256/03/20 MiladiToShamsi = 1634/12/30 Date_GregorianToSolar = 1635/01/01
ta
2257/03/20 MiladiToShamsi = 1635/12/29 Date_GregorianToSolar = 1635/12/30
2289/03/20 MiladiToShamsi = 1667/12/30 Date_GregorianToSolar = 1668/01/01
ta
2290/03/20 MiladiToShamsi = 1668/12/29 Date_GregorianToSolar = 1668/12/30
2322/03/21 MiladiToShamsi = 1700/12/30 Date_GregorianToSolar = 1701/01/01
ta
2323/03/21 MiladiToShamsi = 1701/12/29 Date_GregorianToSolar = 1701/12/30
2355/03/21 MiladiToShamsi = 1733/12/30 Date_GregorianToSolar = 1734/01/01
همون طور که می بینید در تاریخ های بالا (و تمام تاریخ های بین اون، و ایضا تاریخ های دیگه ای که دیگه ادامه ندادم) خروجی برنامه شما با برنامه من فرق داره.
تاریخ های بالا در سایت www.time.ir تست شد و خروجی برنامه شما اشتباه و خروجی برنامه من درست بود.
همون طور که گفتم در بازه قبل از 1634/12/30 شمسی برنامه شما درست کار می کنه. ولی بعد از این تاریخ اشتباهات شروع می شه..
MohsenB
دوشنبه 21 مرداد 1392, 00:19 صبح
سلام
باتشکر از یوسی جان و با اجازه ایشون
اول اینکه تغییراتی که برای اجرا توی فری پاسکال ( + لازاروس ) لازمه رو انجام دادم و دومم یه مثال با دلفی و لازاروس اضافه کردم . امیدوارم که مورد استفاده قرار بگیره .
موفق باشید
khoshblagh
جمعه 25 بهمن 1392, 20:02 عصر
با سلام خدمت اساتید محترم
میخواهم با عبارت زیر تاریخ فرضا امروز را در یک متغیر قرار داده و از یک فیلد که در آن تاریخ میباشد کسر نمایم و نتیجه را که قطعا تعداد روزهای متفاوتی میباشد در فیلدی دیگری وارد نمایم . ولی عبارت نوشته شده دچار خطای سینتکس میشود . چرا؟
strEmroz:=Date_CurrentDate(dbSolar);
cmdUpdateRozMondeh.CommandText:='UPDATE tblTazmin SET RozMondeh='+
Date_DaysBetween(+'TarikhPayan',strEmroz,dbSolar) +
' WHERE (NoaZmanat = 0) AND (VazTazmin = 0) OR (VazTazmin = 1);
یوسف زالی
شنبه 26 بهمن 1392, 09:01 صبح
شما نمی تونی از توابع دلفی در اس کیو ال استفاده کنی.
Date_DaysBetween(+'TarikhPayan',strEmroz,dbSolar)
اینجا شما داری رشته رو مقایسه می کنی.
قبلش باید بریزی در یک متغیر، بعد با توابع دلفی حساب کتاب کنید، بعدش که Date_DaysBetween مقدارش رو داد، ازش استفاده کنید.
BORHAN TEC
سه شنبه 04 شهریور 1393, 10:26 صبح
با سلام،
به نظرم این یونیت یک ایراد اساسی داره و اون هم در تبدیلات تاریخ هست. در سیستم میشه تنظیمات تاریخ رو طوری عوض کرد که مثلاً به جای / در تاریخها از - و یا کاراکترهای دیگه استفاده بشه و یا اینکه جای روز و ماه و سال رو جابجه کنیم و ... .توی این یونیت برای تبدیلات تاریخ رو به صورت رشته میگیره که کار پردازش رو به شدت سخت میکنه و گاهی غیر ممکن میکنه و فکر می کنم استفاده از این روش اصلاً کار درستی نباشه. به نظر من هرجایی که کار تبدیل تاریخ (از میلادی به شمسی و یا هر مدل دیگری) انجام میشه ورودی تابع باید از نوع TDateTime و امثالهم باشه و نه از نوع رشته. :متفکر:
یوسف زالی
سه شنبه 04 شهریور 1393, 10:59 صبح
ورودی و خروجی برای سادگی رشته گرفته شده. خیلی از مواقع در دیتابیس ها و البته گزارشات دسترسی به نوع استاندارد وجود نداره. البته اگر هم داشته باشه برای تبدیل به شمسی باز باید روز و ماه و سالش در بیاد. کار با رشته ساده تره، اما می تونستیم مثلا با نوع Word هم کار کنیم. اساس کار یک سری تبدیلات بر اساس اعداده، ورودی و خروجی چندان اهمیتی نداره، تو سرعت هم به چشم نمیاد :چشمک:
BORHAN TEC
سه شنبه 04 شهریور 1393, 12:23 عصر
ورودی و خروجی برای سادگی رشته گرفته شده. خیلی از مواقع در دیتابیس ها و البته گزارشات دسترسی به نوع استاندارد وجود نداره. البته اگر هم داشته باشه برای تبدیل به شمسی باز باید روز و ماه و سالش در بیاد. کار با رشته ساده تره، اما می تونستیم مثلا با نوع Word هم کار کنیم. اساس کار یک سری تبدیلات بر اساس اعداده، ورودی و خروجی چندان اهمیتی نداره، تو سرعت هم به چشم نمیاد :چشمک:
توضیح دادی، رفاقتمون سر جاش ولی از اونجایی که توی مسائل فنی خیلی جدی هستم توضیحاتت نتونست من رو قانع کنه. :قلب:چون شرایط مختلفی وجود داره حداقل برای تبدیل میلادی به شمسی ورودی باید به صورت TDateTime باشه و بجای استفاده از پردازش رشته برای بدست آوردن ماه، سال، و روز باید حتماً و حتماً از توابع داخل یونیت DateUtils که شامل توابع YearOf و MonthOf و DayOf هست استفاده بشه و استفاده از کد به کار رفته زیر اصلاً درست نیست:
function Date_IsValidDate(Dt: string; DateBase: TDateBase): boolean;var
DD, MM, YY: integer;
begin
if length(Dt) <> 10 then
begin
Result := false;
exit;
end;
DD := StrToInt(Copy(Dt, 9, 2));
MM := StrToInt(Copy(Dt, 6, 2));
YY := StrToInt(Copy(Dt, 1, 4));
// ...
end;
در حالت کلی برای انجام این تبدیلات استفاده از پردازش رشته و استفاده از تابع Copy و نظایر آن اشتباه ترین کار ممکن است. مثلاً در کد بالا فرض کن که تاریخ به صورت 2012/6/1 باشه و پشت ماه و روز عدد 0 نباشه. خوب حالا چه مشکلی به وجود میاد؟! :متفکر: درسته در بالا طول 10 چک شده ولی چرا موقعی که صفر پشت ماه یا روز نوشته نشه تابع نباید درست کار کنه؟ واقعاً چرا؟
یوسف زالی
سه شنبه 04 شهریور 1393, 13:03 عصر
این یونیت یک یونیت قدیمی برای یکی از کامپوننت هام هست. در اون جا هم کنترل های لازم همگی انجام شده و کاربر نمی تونه خارج از قواعد چیزی بزنه، سرسختیت همیشه برام مهم و ارزشمند بوده و هست. بعضی از کدهایی که به نظر بی مورد یا عجیب میاد، در اصل کات شده ی کد اصلی من بود. بعضی جاها مثلا چک شده تا صفر بودن تاریخ (!!) بررسی بشه، دلیلش هم چیزی بود که بیان کردم.
کد به طور صحیح کار می کنه، و می شه ازش استفاده کرد، اما بهینه نیست. مخصوصا در استفاده از تبدیل معکوس با استفاده از روش ریشه یابی دودویی.
خیلی خوبه که گیر بدی، باعث افزایش دقت من هم می شه.
اصلا یکی از موارد دیگه ای که باید در این کد رعایت بشه، FormatSetting هست.
مواردی که گوشزد کردی، به جاست.
مهم ترین دلیلی که این یونیت اینجا گذاشته شد، بحث آموزشی قضیه هست، و مهم تر از اون این که مشکل همیشگی با تاریخ های کبیسه حل بشه. باقی توابع و ورودی ها همگی قابل بازنویسی هستند.
از این که می بینم کدهای من توسط عزیزان حرفه ای تر از من بررسی می شه و نقطه نظراتشون رو می گن، باعث خوشحالی منه.
کارت در اومد، باید کدی رو که از نظر خودت درسته، یا از اون بهتر، اصلاح شده یونیت من رو بگذاری اینجا :لبخند:
خوبت بشه!
BORHAN TEC
سه شنبه 04 شهریور 1393, 13:15 عصر
از این که می بینم کدهای من توسط عزیزان حرفه ای تر از من بررسی می شه و نقطه نظراتشون رو می گن، باعث خوشحالی منه.
امیدوارم که منظورت من نبوده باشم. شما خودت استاد ما هستی. :قلب:
اصلا یکی از موارد دیگه ای که باید در این کد رعایت بشه، FormatSetting هست.
کاستی های مختلفی داره. مثلاً موقعی که یک تاریخ رو به صورت رشته به تابع میدیم کاربر حتماً در پارامتر دیگری از همون تابع باید فرمت تاریخ رو وارد کنه و ... .
کارت در اومد، باید کدی رو که از نظر خودت درسته، یا از اون بهتر، اصلاح شده یونیت من رو بگذاری اینجا
:لبخند:
خوبت بشه!
باشه، این پروژه که دارم روش کار می کنم تموم شد این یونیت رو تا جایی که سوادم برسه اصلاح میکنم. :لبخند:
یوسف زالی
چهارشنبه 02 مهر 1393, 23:05 عصر
مثلاً موقعی که یک تاریخ رو به صورت رشته به تابع میدیم کاربر حتماً در پارامتر دیگری از همون تابع باید فرمت تاریخ رو وارد کنه
این کاستی نیست، اتفاقا قدرته، کاربر می تونه با یک تابع هم کارای شمسی کنه هم میلادی، به طور مثال انتقال تاریخ به چند رو بعد / قبل، شمسی با میلادی فرق داره. از طرفی پیش فرض داره به این معنی که برنامه نویس هیچی هم نداد، نداد.
منتظر کدت هستم، بالاخره دو تا مغز دو تا فکر دارند که مسلما از یک فکر بهتره.
:چشمک:
ariopax
چهارشنبه 02 مهر 1393, 23:29 عصر
سلام
آقا این یونیت رو چطور میشه تبدیلش کرد به یه تقویم .مثل Calender خود دلفی .ویا دیگر کامپوننتها
یوسف زالی
پنج شنبه 03 مهر 1393, 00:25 صبح
سلام. من این کار رو قبلا ها برای شرکتی که توش کار می کردم کرده بودم، باید کامپوننت براش بنویسی و توابع رو در اون بگنجونی، یک دموی خیلی خلاصه روی دلفی هفت ازش دارم که براتون می گذارم.
ariopax
پنج شنبه 03 مهر 1393, 01:12 صبح
باتشکرازشما.
فکر میکنم اشتباه شده .چون این فیلم آموزش اینتراوبه.اگه امکان داره دموی کامپوننت رو یه باردیگه آپلودکنید.
باتشکر
یوسف زالی
پنج شنبه 03 مهر 1393, 01:31 صبح
لینک ها تصحیح شد.
hadisalahi2
شنبه 10 آبان 1393, 10:04 صبح
یوسف جان من توی این یونیت به یک مشکل خوردم
متاسفانه اختلاف بین دو تاریخ رو درست برام محاسبه نمیکنه
ولی وقتی با XCalendarمحاسبه کردم جواب درست رو بهم داد
میشه یک نمونه خودت تست کنی
من اختلاف دو تاریخ رو به رو میخواستم که اختلاف محاسبه خیلی زیاد بود
مثلا حدود 200 روز اشتباه محاسبه کرده بود
ممنونم
یا حق
یوسف زالی
شنبه 10 آبان 1393, 10:34 صبح
تاریخ هات رو بگذار لطفا. احتمالا فرمت اشتباه دادی
hadisalahi2
شنبه 10 آبان 1393, 11:33 صبح
دقیقا تاریخ هایی که گذاشته بودم رو یادم نمیاد
چون عجله داشتم این قسمتش رو با XCalenar انجام دادم
ولی مثلا این دو تا تاریخ رو چک کن و روش فراخوانی تابع رو هم بی زحمت بنویس
1392/01/31
1393/08/10
یکی از خوبیهای کدی که نوشتی اینه که روی تاریخ های 31 و 30 ماهها گیر نمیده
در صورتی که Xcalenadr با این موضوع مشکل داره
یوسف زالی
شنبه 10 آبان 1393, 12:10 عصر
ShowMessage(IntToStr(Date_DifDate('1392/01/31', '1393/08/10', dbSolar)));
یوسف زالی
شنبه 10 آبان 1393, 12:11 عصر
این طور اصلاح کنید:
function Date_DifDate(Dt1, Dt2: string; DateBase: TDateBase): integer;
var
D1, D2: TDate;
begin
if DateBase = dbSolar then
begin
Dt1 := Date_SolarToGregorian(Dt1);
Dt2 := Date_SolarToGregorian(Dt2);
end;
D1 := StrToDate(Dt1, FormatSetting);
D2 := StrToDate(Dt2, FormatSetting);
Result := abs(DaysBetween(D1, D2)) * IfThen(D1 < D2, 1, -1);
end;
hadisalahi2
شنبه 10 آبان 1393, 15:11 عصر
این کد تست شده هستش دیگه؟
آیا قبلا مشکل داشت یا من اشتباه فراخوانی کرده بودم؟
یوسف زالی
شنبه 10 آبان 1393, 15:41 عصر
یکم فرق کرده. تو پروژه های من داره کار می کنه. دوس سالی هم هست ریپورتی نداشتم.
rezamahdizadeh
یک شنبه 23 آذر 1393, 04:04 صبح
سلام
آیا کد تبدیلهای تاریخ به همدیگر در SQL Server با همین الگوریتم و دقت را نیز دارید؟
جناب You-See این کامپوننت ورود تاریخ که در کلیپی در پست 38 لینک داده اید خودتان نوشته اید؟
یوسف زالی
یک شنبه 23 آذر 1393, 10:24 صبح
کد تبدیل در اس کیو ال رو ندارم ولی می شه به راحتی تبدیلش کرد. زیاد سخت نیست.
باید تابع رو تبدیل به تابع اسکالر در اس کیو ال کنید.
بله. اون کامپوننت یکی از کارهای من هست.
hadisalahi2
یک شنبه 23 فروردین 1394, 09:53 صبح
سلام
من چند روز پیش داشتم یک تاریخ رو تبدیل میکردم که متاسفانه خطا داد
من تاریخ 20 فرودین 94 رو میخواستم 7 روز کم کنم
اما متاسفانه پیام خطای Data is invalid رو داد
میشه یک چک بفرمایید
اینم کدش:
Date2:=IncDayShamsi(PublicDate,-7);
PublicDate هم توی تاریخ 1394/01/20 بود
یوسف زالی
یک شنبه 23 فروردین 1394, 10:01 صبح
سلام.
94/01/13
مشکلی نبود. البته با اسامی توابع من، اون اسم تابع رو خودتون بازنویسی کردید؟ کدش درسته؟
hadisalahi2
پنج شنبه 27 فروردین 1394, 11:25 صبح
نه یوسف جان
دقیقا اسم تابعی هستش که توی یونیت شما وجود داره
Function IncDayShamsi(DateValue:String;IncValue:Shortint):S tring;
94/01/13
مشکلی نبود. البته با اسامی توابع من، اون اسم تابع رو خودتون بازنویسی کردید؟ کدش درسته؟
این تاریخ مشکل نیست
تاریخ 1394/01/20 مشکل داره
یعنی به این تاریخ گیر میده و این خطا رو میده
Data is invalid
من هیچ تغییری در کد شما ندادم
مگه اینکه جدیدا شما تغییری داده باشی که من اون کد رو ندارم
یوسف زالی
پنج شنبه 27 فروردین 1394, 14:57 عصر
می شه کدی که داری رو بگذازی؟
من همچین اسمی ندارم شاید دوستان زحمت کشیدن توسعش دادن.
hadisalahi2
جمعه 28 فروردین 1394, 21:12 عصر
خدمت داش یوسف گل
Function IncMonthShamsi(DateValue:String;IncValue:Shortint) :String;
var ConvertDate:String[10];
Begin
ConvertDate:=Date_SolarToGregorian(DateValue);
ConvertDate:=DateToStr(IncMonth(StrToDate(ConvertD ate),IncValue));
ConvertDate:=Date_GregorianToSolar(ConvertDate);
Result:=ConvertDate;
End;
//QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQ
Function IncDayShamsi(DateValue:String;IncValue:Shortint):S tring;
var ConvertDate:String[10];
Begin
ConvertDate:=Date_SolarToGregorian(DateValue);
ConvertDate:=DateToStr(IncDay(StrToDate(ConvertDat e),IncValue));
ConvertDate:=Date_GregorianToSolar(ConvertDate);
Result:=ConvertDate;
End;
یوسف زالی
جمعه 28 فروردین 1394, 21:18 عصر
با این تست کن:
function Date_MoveDate(Dt: string; Step: integer; DateBase: TDateBase): string;
var
D: TDate;
begin
if DateBase = dbSolar then
Dt := Date_SolarToGregorian(Dt);
D := StrToDate(Dt, FormatSetting) +Step;
Dt := DateToStr(D, FormatSetting);
if DateBase = dbSolar then
Dt := Date_GregorianToSolar(Dt);
Result := Dt;
end;
hadisalahi2
شنبه 29 فروردین 1394, 12:29 عصر
الان که دقت کردم ، این کد قبلا توی یونیت شما بوده ، اما من متوجه نشدم
حالا نمیدونم چطور دو تا تابع افزودن یا کاهش تاریخ توی این یونتی هست :متفکر:
داش یوسف ، این تابع فقط برای اضافه کردن روز استفاده میشه؟
اگه بخوایم کم کنیم از یک تاریخ چی؟
حالا برای کاهش یا افزایش ماه چی؟
یوسف زالی
شنبه 29 فروردین 1394, 14:28 عصر
این تابع برای روزه. برای ماه فک کنم همونجا وجود داشت.
منفی بذاری می ره عقب.
hadisalahi2
شنبه 29 فروردین 1394, 17:25 عصر
این تابع منظورته دیگه؟
Function IncMonthShamsi(DateValue:String;IncValue:Shortint) :String;
مشکلی توی محاسبات نداره؟
یوسف زالی
سه شنبه 01 اردیبهشت 1394, 14:53 عصر
من چنین تابعی ندارم!
hadisalahi2
سه شنبه 01 اردیبهشت 1394, 18:03 عصر
اسم اون تابع ماه چیه عزیزم؟
تابعی به غیر از این برای ماه توی یونیت مشاهده نمی فرمایم :لبخند:
یوسف زالی
سه شنبه 01 اردیبهشت 1394, 22:00 عصر
من برای ماه تابعی ننوشتم، اما خیلی خیلی ساده است. قسمت وسط رو بردار، اضافه و کم کن، تقسیم بر 12 اون رو هم با سال اوکی کن.
لازمه برات بنویسم؟ فک کنم دیگه خودت استاد این کارایی دیگه.
hadisalahi2
چهارشنبه 02 اردیبهشت 1394, 11:41 صبح
شرمنده داداش
اون وسطش رو نفهمیدم :لبخند:
شما که زحمت کشیدی ، اون دوخط رو هم اضافه کن :خجالت:
یوسف زالی
چهارشنبه 02 اردیبهشت 1394, 13:11 عصر
این رو الان نوشتم، تست کن بهم بگو.
function Date_MoveMonth(Dt: string; Step: integer; DateBase: TDateBase): string;
var
years, months, days: integer;
SYear, SMonth, SDay: integer;
MaxValid: integer;
begin
SYear := StrToInt(Copy(Dt, 1, 4));
SMonth := StrToInt(Copy(Dt, 6, 2));
SDay := StrToInt(Copy(Dt, 9, 2));
years := Step div 12;
months := Step mod 12;
SYear := SYear + years;
SMonth := SMonth + months;
if SMonth > 12 then
begin
dec(SMonth, 12);
inc(SYear);
end;
if SMonth < 1 then
begin
inc(SMonth, 12);
dec(SYear);
end;
MaxValid := Date_DaysPerMonth(SYear, SMonth, DateBase);
SDay := IfThen(SDay > MaxValid, MaxValid, SDay);
Result := RightStr('000' + IntToStr(SYear), 4) + '/' + RightStr('0' + IntToStr(SMonth), 2) + '/' + RightStr('0' + IntToStr(SDay), 2);
end;
golbafan
چهارشنبه 02 اردیبهشت 1394, 13:44 عصر
سلام دوست عزیز
مواردی که زحمت کشیدید رو میخوام از دو منظر نقد کنم
قبلش هم مجدد از زحمات شما قدر دانی میکنم
نقد من به کار شما:
1- آیا واقعا دقت 5000 ساله لازمه یا نه ؟؟ درسته از لحاظ برنامه نویسی کار جالبیه ولی آیا از لحاظ منطقی هم جالبه؟؟؟
و این مطلب که با تقویم رسمی ایران چک کردین و یکسان بوده باز هم دلیل بر دقت اون نمیشه چرا که سایت تقویم رسمی ایران هم داره از یک همچین الگوریتمی استفاده میکنه و در واقع کار شما فقط یک پیاده سازی مجدد میتونه باشه!
2- کامپوننت رایگان، اپن سورس و بسیار دقیقی به نام xcalendar وجود داره که نه تنها میلادی و شمسی رو تبدیل میکنه بلکه تقویم هجری قمری رو نیز با دو روش محاسبه و تبدیل میکنه
روش عادی و روش Astro که دقیق تر هست و با استفاده از علم ستاره شناسی کار میکنه
همچنین شامل توابع زیادی میشه که برای کار با تاریخ در دیتابیس و یا بصورت عادی میشه از اونها استفاده کرد.
این نکته دوم رو بابت این عرض کردم که خدمتتون یاد آوری کنم که لازم نیست هر چیزی رو در امضای خودمون قرار بدیم
3- اما بدترین خاصیت یونیت شما استفاده از رشته هاست و همینطور در نظر نگرفتن formatstring استاندارد!
با تشکر فراوان
سعی میکنم مواردی رو که گفتم برات اصلاح کنم بزارم اینجا
یوسف زالی
چهارشنبه 02 اردیبهشت 1394, 14:12 عصر
کار خوبی می کنید نقد می کنید. بنده با این که انتقاد رو دوست ندارم (!!) اما همیشه در موردش فکر می کنم و سعی در اصلاح مواردی که به نظرم واقعیه می کنم.
1- در مورد سورس:
مرجع تاریخ رسمی ایران تقویم رسمی ایرانه و باید با اون چک بشه. این که شما یه برنامه حسابداری می نویسی آیا پیاده سازی مجدد اون نیست؟ خب برو بخرش راحت تره که!
این نقد رو وارد نمی دونم. بنده جنبه آموزشی اون رو مد نظر دارم و نه تبلیغ، که اصلا از این موارد نه پولی در میارم و نه حاضرم در بیارم، همونطور که می بینید دیباگ رایگان هم ارائه داده می شه.
در مورد کامپوننت رایگان، اول که کار خوبی می کنید معرفی می کنید، تا دوستان و من هم ازش استفاده کنیم.
اما صرف وجود چنین کامپوننتی دلیل نمی شه کار دیگه ای انجام نشه، فکر می کنم در اوایل همین تاپیک مطرح کردم که این نمونه سورس آموزشی هست و از دل کامپوننتی که برای شرکتم نوشتم بیرون کشیدم. بنابراین ذاتا و طبیعتا جایگاهی نداره که از کامپوننت مورد معرفی شما در دل کامپوننت خودم wrap کنم.
یونیت بهترین یونیت در مارکت نیست، با اسمبلی بنویسی خیلی سریعتر هم می شه، اصراری هم بر این که بهترین سورس نوشته شده نیست.
رشته ای بودن دلایل متعدد داره و برای نیاز من و جند نفر از دوستان انجام شده. تبدیل توابع از رشته ای به استاندارد فکر نمی کنم کلا یکی دو ساعت برای کل یونیت زمان بگیره.
2- در مورد گذاشتن لینک در امضا:
این که در امضای بنده چه چیزی هست کاملا شخصی هست. موارد موجود در امضای هر شخص اگر از فیلتر قانون رد شده باشه به کسی مرتبط نیست. این از این جهت که بصورت عمومی ایراد گرفتید.
اما دلیل وجودش رو براتون می گم، مدیران سایت معمولا بیشترین افرادی هستند که بهشون ارجاع می شه، در خصوصی / در تاپیک ها / درخواست ها / گزارشات کاربران / شکایات و ...
لینکی که در امضا گذاشته شده در حقیقت مشکل خیلی از دوستان بود که چه در سایت چه بصورت تلفنی خواسته شده بود. وجود این لینک یعنی دسترسی سریع تر و بدون نیاز به جستجو برای دوستان من. اگر شما ایرادی وارد می دونید که از قوانین تخطی شده، می تونید با مدیران ارشد در میون بگذارید. اما اگر نیت طعنه زدن هست (که بعید می دونم) بنده نیازی به معرفی شدن خودم نمی بینم، مدیران ارشد دوستان مستقیم بنده هستند (بعد از مدیریت بنده) و با سایر دوستان مدیر سایر تالار ها هم دوستی و بعضا رفت و آمد هم دارم. من و شما هم اونقدر سرمون شلوغ هست که نیاز نداشته باشیم به "تو بوق کردن یک کار ساده"
3- امید خیلی زیادی دارم که از توانایی دوستان (خصوصا شما) بصورت هدفمند استفاده بشه. درگیر حاشیه شدن رو هیچ وقت دوست نداشتم.
4- یک سر به تالار های دیگه هم بزنید، چکشی برخورد کردن رو هرگز دوست نداشتم، اگر هم می بینید که زمان برای این تالار می گذارم، فقط و فقط به عشق دوستان هست و لا غیر.
5- چنانچه انتقاد یا شکایتی از کسی دارید لطفا بصورت خصوصی مطرح کنید. یا با شخص، یا با مدیر مرتبط.
پست های بی ارتباط با این مبحث پاک خواهد شد. در صورتی که قانع نشدید یا دلخوری ای دارید، لطفا با شماره بنده (در پروفایلم هست) تماس بگیرید یا با مدیران ارشد در میون بگذارید.
متشکرم.
hadisalahi2
چهارشنبه 02 اردیبهشت 1394, 16:33 عصر
2- کامپوننت رایگان، اپن سورس و بسیار دقیقی به نام xcalendar وجود داره که نه تنها میلادی و شمسی رو تبدیل میکنه بلکه تقویم هجری قمری رو نیز با دو روش محاسبه و تبدیل میکنه
با این مورد کاملا مخالفم
این کامپوننت با این که بسیار عالی و کاربردیه ، اما محاسبات تاریخش در خیلی جاها دقیق نیست
من با این کامپوننت خیلی کار کردم و ایراداتی پیدا کردم در محاسباتش که مجبور شدم برم سراغ یک یونیت دیگه
بارها هم این مطلب رو گفتم
اما یونیت یوسف جان ، تست کردم و تا الان که خدا رو شکر مشکلی در محاسبه نداشته :لبخند:
البته یک ایراد در اختلاف دو تاریخ وجود داشت که رفع شد
hadisalahi2
چهارشنبه 02 اردیبهشت 1394, 16:41 عصر
4- یک سر به تالار های دیگه هم بزنید، چکشی برخورد کردن رو هرگز دوست نداشتم، اگر هم می بینید که زمان برای این تالار می گذارم، فقط و فقط به عشق دوستان هست و لا غیر.
در این مورد من هم میخواستم بارها توی یکی از پست ها این مطلب رو بگم ، اما گفتم شاید تعریف از خود باشه
من به خیلی از تالارهای سایت مراجعه میکنم مخصوصا به تالار دات نت
این رو به جرات میگم ،که هیچ تالاری در این سایت به اندازه تالار دلفی فعال نیست و اعضای هیچ تالاری به اندازه این تالار به همدیگه کمک نمیکنند
منم امیدوارم به جای بحث های حاشیه ای و بی خود ، تلاشمون رو برای کمک بیشتر به همدیگه بزاریم .
یا حق
golbafan
چهارشنبه 02 اردیبهشت 1394, 23:19 عصر
سلام خدمت دوستان عزیز
اگر از حرفام موردی رو برداشت کردید که ناپسند بوده من همینجا عذز خواهی میکنم چون واقعا قصد جسارت نداشتم
که از این جمله ی آخرم فکر کنم مشخص هست: "سعی میکنم مواردی رو که گفتم برات اصلاح کنم بزارم اینجا"
چون در کل از کلیات کارتون خوشم اومده بود اومدم اینجا پیغام گزاشتم و نظرم رو در موردش دادم وگرنه این کار رو نمیکردم!
اما دلیل نمیشه ضعف هایی رو که میبینم رو بهتون نگم تا رفعش کنید
و باز هم دلیل نمیشه در مقابل انتقاد ها زود برنجیم!!
مخصوصا که انتقاد از شخص شما نبوده بلکه از یونیت هست
البته نقد من از یونیت شما به دلیل سومی که عرض کردم هنوز برام پابرجاست
بازم از زحماتت تشکر میکنم
یوسف زالی
پنج شنبه 03 اردیبهشت 1394, 00:19 صبح
یونیت عاری از عیب نیست. بهینه ترین هم نیست. آموزشیه، و البته برای کار خاص.
زمان لازم رو برای اصلاح ندارم، طبق صلاحدید خودتون می تونید اون رو اصلاح کنید، و اگر چنین کاری کردید خوشحال می شم همینجا بگذارید.
یوسف زالی
سه شنبه 08 اردیبهشت 1394, 10:00 صبح
هادی جان تست کردی؟ اگر مشکلی داشت / نداشت مطرح کن.
hadisalahi2
پنج شنبه 24 اردیبهشت 1394, 10:52 صبح
سلام
داش یوسف به یه مشکل برخورد کردم
اول اینکه تفاوت توابع Date_DifDate با Date_DaysBetween در چیه؟
در اختلاف دو تاریخ ، اشتباه محاسباتی هستش البته برای من
حالا شما چک کنید ببنید کجاش مشکل داره
تاریخ 1392/04/28 الی 1394/02/24 اختلافش رو برمیگردونه : 431
تاریخ 1392/03/26 الی 1393/12/06 اختلافش رو برمیگردونه : 620
تاریخ 1392/04/26 الی 1394/02/24 اختلافش رو برمیگردونه : 429
و چند تای دیگه
البته من از تابع Date_DaysBetween استفاده کردم
میشه لطفا شما چک کنی ببینی این مشکل برای شما هم هست یا نه
hadisalahi2
پنج شنبه 07 خرداد 1394, 17:26 عصر
سلام
دو تا مطلب در مورد یونیت :
1- تایع Date_MoveMonth رو تست کردم ردیف بود و محاسباتش صحیحه.
2- در مورد این اختلاف بین دو تاریخ ، یک نکته جالب فهمیدم و اینکه جای تاریخ ها رو توی فراخوانی تابع عوض کردم ، خروجی درست شد
golbafan
پنج شنبه 07 خرداد 1394, 17:51 عصر
سلام
یک تغییراتی که لازمه بدید اینه که موقع محاسبه اختلاف تاریخ بیاد اونها رو به ترتیب سورت کنید تا این خطا رخ نده
منظورم اینه که یونیت رو ارتقاع بدید
hadisalahi2
شنبه 09 خرداد 1394, 11:56 صبح
منظورم اینه که یونیت رو ارتقاع بدید
راستش رو بخواهی این یک قلم رو اصلا متوجه نشدم
khoshblagh
جمعه 09 بهمن 1394, 23:05 عصر
با سلام خدمت جناب آقای زالی
احتراما در رابطه با تبدیل تاریخ میلادی به شمسی به مشکل زیر مواجه شدم.
در برنامه مورد نظر با تابع()GetDate اس کیو ال 2012 تاریخ سرور را بدست آورده و سپس از تابع تبدیل تاریخ میلادی به شمسی استفاده مینمایم و نتیجه را در دیتا بیس ذخیره مینمایم. بعضی وقتها این تاریخ به صورت 1300/01/01 نمایش و ثبت میشود. البته به نظر من مربوط به ساختار تاریخ میلادی میباشدکه به صورت ماه/روز/سال تعریف شده است. میخواستم بدانم که آیا تاریخ میلادی باید جهت تبدیل به تاریخ فارسی از فرمت ماه/روز/سال باشد و یا فرمت روز/ماه/سال معتبر میباشد. توضیح بیشتر اینکه فقط بعضی وقتها این مشکل از طرف کلاینتها گزارش میشود. ضمن اینکه تاریخ 1300/01/01 در یونیت شما به عنوان تاریخ غیر معتبر معرفی شده است . متشکرم
یوسف زالی
شنبه 10 بهمن 1394, 01:08 صبح
سلام.
شما وقتی ورودی استاندارد تاریخ وارد می کنید در حقیقت دارید یک عدد وارد می کنید، اما اگر اون ورودی تبدیل به فرمت رشته ای بشه و فرمت رشته ای رو تبدیل به شمسی کنید، باید ترتیب روز ماه سال رو رعایت کنید.
در این صورت احتمال داره تنظیمات زمان کلاینت مورد نظر اشکال داشته باشه.
یوسف زالی
شنبه 10 بهمن 1394, 01:10 صبح
یک تغییراتی که لازمه بدید اینه که موقع محاسبه اختلاف تاریخ بیاد اونها رو به ترتیب سورت کنید تا این خطا رخ نده
لازمه که هر دو حالت موجود باشه، حتی یونیت خود دلفی هم سورت نمی کنه.
نیازی به این کار نیست. این کار برعهده برنامه نویسه.
khoshblagh
شنبه 10 بهمن 1394, 08:33 صبح
لازمه که هر دو حالت موجود باشه، حتی یونیت خود دلفی هم سورت نمی کنه.
نیازی به این کار نیست. این کار برعهده برنامه نویسه.
شما وقتی ورودی استاندارد تاریخ وارد می کنید در حقیقت دارید یک عدد وارد می کنید، اما اگر اون ورودی تبدیل به فرمت رشته ای بشه و فرمت رشته ای رو تبدیل به شمسی کنید، باید ترتیب روز ماه سال رو رعایت کنید.
در این صورت احتمال داره تنظیمات زمان کلاینت مورد نظر اشکال داشته باشه.[/QUOTE]
با سلام
من به روش زیر اینکار را انجام میدهم. آیا اینکار درست است؟ در ضمن این کد تاریخ سرور را برمیگرداند پس احتمالا تنظیمات زمان کلاینت نباید روی آن تاثیر داشته باشد! خواهشمندم بیشتر راهنمایی بفرمائید.
qryDateTimeServer.Close;
qryDateTimeServer.SQL.Clear ;
qryDateTimeServer.SQL.Add('SELECT GetDate() AS GD');
qryDateTimeServer.Open;
strDate:=Copy(qryDateTimeServer.FieldByName('GD'). Asstring,1,10);
strDate:=Copy(strDate,7,4)+'/'+Copy(strDate,1,2)+'/'+Copy(strDate,4,2);
mskTarikhSabtWahed.Text:=Date_GregorianToSolar(str Date);
strTime:=Copy(qryDateTimeServer.FieldByName('GD'). Asstring,12,8);
edtSaatKarbar.Text:=strTime;
یوسف زالی
شنبه 10 بهمن 1394, 10:07 صبح
روال کار متد AsString رو عینا براتون می گذارم:
procedure TDateTimeField.GetText(var Text: string; DisplayText: Boolean);
var
F: string;
D: TDateTime;
begin
if GetValue(D) then
begin
if DisplayText and (FDisplayFormat <> '') then
F := FDisplayFormat
else
case DataType of
ftDate: F := ShortDateFormat;
ftTime: F := LongTimeFormat;
end;
DateTimeToString(Text, F, D);
end else
Text := '';
end;
همون طور که می بینید فقط دیتا از سرور میاد و تبدیلاتش در دلفی سمت کلاینت انجام می شه و تنظیمات سیستم روی اون موثره.
یوسف زالی
سه شنبه 08 تیر 1395, 21:34 عصر
قطعه کدتون رو بگذارید تست کنم.
masoud_salimy
سه شنبه 08 تیر 1395, 22:13 عصر
باتشكر
شما خودتون براي نوشتن برنامه هاي تجاريتون از اين كدها براي تبديل تاريخ استفاده ميكنيد يا از كامپوننت خاصي استفاده ميكنيد؟
بازهم ممنون بابت پاسخ گويي و زماني كه ميگذاريد
یوسف زالی
سه شنبه 08 تیر 1395, 23:04 عصر
چهار ساله که از همین استفاده می کنم
fahimi
پنج شنبه 10 تیر 1395, 17:47 عصر
با سلام
با تشکر لطف آقای یوسف زالی درخصوص ارایه تابع تاریخ.
در صورتیکه ورودی تابع فرمت تاریخ سیستم yyyy-DD-mm نباشد برنامه دچار خطا می شود با توجه به اینکه اکثریت فرمت تاریخ سیستم yyyy/DD/mm می باشد.در صورت امکان تغییراتی در تابع داده می شد فرمت های مختلف تاریخ سیستم تاثیری در عملکرد آن نداشته باشد.
با تشکر
یوسف زالی
پنج شنبه 10 تیر 1395, 21:14 عصر
سر فرصت تابع رو با عملیات ریاضی بازنویسی می کنم و از وابستگی رشته درش میارم.
اما برای رفع اشکال باید تنظیمات اولیه یونیت رو اعمال کنید.
menal majmoe
شنبه 19 آبان 1397, 13:53 عصر
سلام
وقتتون بخیر
بالاخره تابع agec کو ؟؟؟ من که پیداش نکردم.محاسبه کامل سن نه فقط سال.
ATULICUS
دوشنبه 27 بهمن 1399, 15:44 عصر
سلام
تا دوست عزیزمون وقت خالی برا بهینه کردن و بازنویسی یونیتشون پیدا می کنند ، دوستان چه پیشنهادی میدن برا یونیت یا کامپوننت شمسی ؟!
کسی کامپوننت i18n رو تست کرده ببینه محاسباتش درسته یا نه ؟!
یونیت persiandate رو کسی تست کرده !؟
یوسف زالی
دوشنبه 27 بهمن 1399, 16:25 عصر
سلام. چنین تابعی اصلا در توابع من نیست،
در خصوص بهینه سازی، دیگه برام توجیه زمانی نداره دوست گرامی.
بهینه سازی از رشته ای به عددی هم از نظر زمانی تقریبا توفیری نمی کنه، مگه این که تو حلقه های تعداد بالا درگیرش باشی.
برای کارهای نرمال همین جواب می ده، خود من روی پخش مویرگی دارم ازش استفاده می کنم.
موفق باشید.
h.kalagh
سه شنبه 13 آذر 1403, 17:04 عصر
سلام
ممنون بابت این کد عالی که بعد 11 سال به کمک اومد:خجالت::تشویق:
دلفــي
شنبه 24 آذر 1403, 09:12 صبح
https://barnamenevis.org/showthread.php?590971
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.