Validation error in Jalali/persian date - c#

I am developing application in Arabic/Dari/Pashto (for Afghanistan) using C# and also using Jalali/Persian calendar for date selection. I want to validate input date before saving into database. I am using below function for validation and passing Jalali/Persian calendar date to this function. It works perfectly when user select date something like "28/02/1393" but it throws error for date "31/02/1393". Both dates are valid Jalali/Persian date.
I think this issue is happenning because somehow application considering this date is English and there is no any 31st day in 2nd month in English calendar. Please help me to find solution for that.
static public bool ValidateParsianDate(string date)
{
bool status = true;
try
{
PersianCalendar persianCalendar = new PersianCalendar();
CultureInfo persianCulture = new CultureInfo("fa-IR");
DateTime persianDateTime = DateTime.ParseExact(date, "dd/MM/yyyy", persianCulture);
}
catch (Exception ex)
{
string msg = ex.Message;
status = false;
}
return status;
}
Thanks & Regards,
Rajeev

Use the PersianCalendar.ToDateTime(
int year,
int month,
int day,
int hour,
int minute,
int second,
int millisecond,
int era
) method.
static public bool ValidateParsianDate(string date)
{
bool status = true;
try
{
PersianCalendar persianCalendar = new PersianCalendar();
var dateParts = date.Split(new char[] { '/' }).Select(d=> int.Parse(d)).ToArray();
var date = persianCalendar.ToDateTime(dateParts[2], dateParts[1], dateParts[0], 0, 0,0,0, /*8 era of year here **/);
}
catch (Exception ex)
{
string msg = ex.Message;
status = false;
}
return status;
}

Because persianCulture.Calendar is set to GregorianCalendar by default in .NET framework and can't be changed to PersianCalendar without using the reflection. more info here

I had that problem but i used this and it work
public static bool IsValidDate(string date)
{
var regex = new Regex("^\\d{ 4 } /\\d{ 2}/\\d{ 2}$");
var arrPattern = new[] {
new Regex("^\\d{4}/\\d{2}/\\d{2}$"),
new Regex("^\\d{ 4 } /\\d{ 2}/\\d{ 1}$"),
new Regex("^\\d{ 4 } /\\d{ 1}/\\d{ 2}$"),
new Regex("^\\d{ 4 } /\\d{ 1}/\\d{ 1}$"),
new Regex("^\\d{ 2 } /\\d{ 2}/\\d{ 2}$"),
new Regex("^\\d{ 2 } /\\d{ 2}/\\d{ 1}$"),
new Regex("^\\d{ 2 } /\\d{ 1}/\\d{ 2}$"),
new Regex("^\\d{ 2 } /\\d{ 1}/\\d{ 1}")
};
const int kabise = 1387;
var year = 0;
var mounth = 0;
var day = 0; var flag = false;
foreach (var t in arrPattern)
{
if (t.IsMatch(date))
flag = true;
}
if (flag == false) return flag;
//جدا کننده تاریخ می تواند یکی از این کاراکترها باشد
var splitDate = date.Split('/','-',':');
year = Convert.ToInt32(splitDate[0]);
mounth = Convert.ToInt32(splitDate[1]);
day = Convert.ToInt32(splitDate[2]);
if (mounth > 12 || mounth <= 0)
flag = false;
else
{
if (mounth< 7)
{
if (day > 31)
{
flag = false;
}
}
if (mounth != 12) return flag;
var t = (year - kabise) % 4;
if ((year - kabise) % 4 == 0)
{
if (day >= 31)
flag = false;
}
else if (day >= 30)
flag = false;
}
return flag;
}

Related

Compare Date is Greater than in C#

I'm trying to check if the passing variable date is greater than a static date which I have included in the code and currently trying to use the following code,
private String LastPayDate {
get {
string foo;
if(Parameters.TryGetValue("Last Pay Date", out foo))
return foo;
else
return null;
}
}
private Boolean IsLastPay() {
if (!string.IsNullOrEmpty(LastPayDate)) {
if(DateTime.Parse(Parameters.TryGetValue("Last Pay Date") >="24/05/2018")
return true;
else
return false;
}
return false;
}
however the only error I get is within below code section,
if(DateTime.Parse(Parameters.TryGetValue("Last Pay Date") > "24/05/2018")
can anyone help please ?
If you want to compare DateTimes, compare them, but not strings:
//TODO: what is the magic number (date) 24 May 2018?
private Boolean IsLastPay() {
if (Parameters.TryGetValue("Last Pay Date", out var dateSt))
if (DateTime.TryParse(dateSt, out var paramDate))
return paramDate >= new DateTime(2018, 5, 24);
else
return false; // DateTime.TryParse failed to parse the parameter
else
return false; // Parameters.TryGetValue failed to get the value
}
Thank you for respond. It did helped and I've managed to use below code and its working now, Much appreciate Help!
private Boolean IsLastPay()
{
if (!string.IsNullOrEmpty(LastPayDate))
{
string lpd;
}
if(Parameters.TryGetValue("Last Pay Date", out lpd))
{
if(DateTime.Parse(lpd) > new DateTime(2018,05,24))
return true;
else
return false;
}
}
return false;
}
Why not use the DateTime.Compare() method of DateTime class.
For this you need to have both the variables/objects of type DateTime.
string staticDate = "24/05/2018"; //dd-MM-yyyy
string inputDate = "14/08/20"; //dd-MM-yy
string greaterDate = CalculateGreaterDate(inputDate, staticDate); // 14/08/20 is greater
public static string CalculateGreaterDate(string iDate, string sDate)
{
// input date
string input = iDate;
var inputElements = input.Split('/');
int inputDay = Convert.ToInt32(inputElements[0]); //14
int inputMonth = Convert.ToInt32(inputElements[1]); //08
int inputYear = Convert.ToInt32(inputElements[2]); //20
// static date
string static = sDate;
var staticElements = static.Split('/');
int staticDay = Convert.ToInt32(staticElements[0]); //24
int staticMonth = Convert.ToInt32(staticElements[1]); //05
int staticYear = Convert.ToInt32(staticElements[2]); //2018
DateTime inputDate = new DateTime(inputYear, inputMonth, inputDay);
DateTime staticDate = new DateTime(staticYear, staticMonth, staticDay);
// DateTime.Compare(d1, d2) returns:
// > 0 : d1 is greater than d2
// = 0 : d1 & d2 are equal
// < 0 : d1 is smaller than d2
int result = DateTime.Compare(inputDate, staticDate);
if (result > 0)
return iDate + " is greater";
else if (result < 0)
return sDate + " is greater";
else if (result == 0)
return iDate + " is equal to " + sDate;
}

Calling Get Months between 2 dates C#

I am trying to call the GetMonths() method during the Row_Inserting() method but it shows me an error. Also, how do I copy the value of this method to a variable named Total_Pay?
public override bool Row_Inserting(OrderedDictionary rsold, ref OrderedDictionary rsnew)
{
GetMonths(FROM_DATE, TO_DATE);
return true;
}
public int GetMonths(DateTime FROM_DATE, DateTime TO_DATE)
{
if (FROM_DATE > TO_DATE)
{
throw new Exception("Start Date is greater than the End Date");
}
int months = ((TO_DATE.Year * 12) + TO_DATE.Month) - ((FROM_DATE.Year * 12) + FROM_DATE.Month);
if (TO_DATE.Day >= FROM_DATE.Day)
{
months++;
}
return months;
}
Hope this helps..
public override bool Row_Inserting(OrderedDictionary rsold, ref OrderedDictionary rsnew)
{
int Total_Pay;
DateTime FROM_DATE = DateTime.Parse("02-May-2016"); //Replace with date you need
DateTime TO_DATE = DateTime.Parse("08-May-2016"); //Replace with date you need
Total_Pay = GetMonths(FROM_DATE, TO_DATE);
return true;
}
public int GetMonths(DateTime FROM_DATE, DateTime TO_DATE)
{
if (FROM_DATE > TO_DATE)
{
throw new Exception("Start Date is greater than the End Date");
}
int months = ((TO_DATE.Year * 12) + TO_DATE.Month) - ((FROM_DATE.Year * 12) + FROM_DATE.Month);
if (TO_DATE.Day >= FROM_DATE.Day)
{
months++;
}
return months;
}
And checkout this similar question Link

Regex c# - where to insert the blank space

I want to allow the user to enter the year in blank but I don´t know where to put \s\s\s\s in the following expression.
Here is an example of what I need to do: if the user inserts 03-07-_____ the program must be executed every 3Th of July of each year(and it proceeds the same way if the user inserts blank date, month or year or twoo of this three)
System.Text.RegularExpressions.Regex rdate =
new System.Text.RegularExpressions.Regex(#"^((((0?[1-9]|[12]\d|3[01]|\s\s|\s\d)[\-](0?[13578]|1[02]|\s\s)[\-]((1[6-9]|[2-9]\d)?\d{2}))|((0?[1-9]|[12]\d|30)[\-](0?[13456789]|1[012])[\-]((1[6-9]|[2-9]\d)?\d{2}))|((0?[1-9]|1\d|2[0-8])[\-]0?2[\-]((1[6-9]|[2-9]\d)?\d{2}))|(29[\-]0?2[\-]((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00)))|(((0[1-9]|[12]\d|3[01])(0[13578]|1[02])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|[12]\d|30)(0[13456789]|1[012])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|1\d|2[0-8])02((1[6-9]|[2-9]\d)?\d{2}))|(2902((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00))))$");
Could someone help me?(this expression validates even a leap year)
Here is what You asked for
System.Text.RegularExpressions.Regex rdate =
new System.Text.RegularExpressions.Regex(#"^((((0?[1-9]|[12]\d|3[01]|\s\s|\s\d)[\-](0?[13578]|1[02]|\s\s)[\-]((1[6-9]|[2-9]\d)?\d{2}|\s\s\s\s))|((0?[1-9]|[12]\d|30)[\-](0?[13456789]|1[012])[\-]((1[6-9]|[2-9]\d)?\d{2}|\s\s\s\s))|((0?[1-9]|1\d|2[0-8])[\-]0?2[\-]((1[6-9]|[2-9]\d)?\d{2}|\s\s\s\s))|(29[\-]0?2[\-]((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00|\s\s\s\s)))|(((0[1-9]|[12]\d|3[01])(0[13578]|1[02])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|[12]\d|30)(0[13456789]|1[012])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|1\d|2[0-8])02((1[6-9]|[2-9]\d)?\d{2}))|(2902((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00))))$");
But I am not sure it is what You really want. The regex was already patched, I continued the way. But not only it is maintenance nightmare, it behaves strange. It accepts empty day, but only when month is january, march, may... or empty. Less lines of code is not always better. I would suggest to rewrite it completely. Something simmilar to this:
protected DateTime? getDateTimeFromParts(string day, string month, string year)
{
DateTime now = DateTime.Now;
int iyear;
if (string.IsNullOrWhiteSpace(year))
{
iyear = now.Year;
}
else
{
iyear = int.Parse(year);
if (iyear >= 0 && iyear < 100) { iyear += 2000; }
}
int imonth;
if (string.IsNullOrWhiteSpace(month))
{
imonth = now.Month;
}
else
{
imonth = int.Parse(month);
}
int iday;
if (string.IsNullOrWhiteSpace(day))
{
iday = now.Day;
}
else
{
iday = int.Parse(day);
}
if (iyear <= DateTime.MaxValue.Year && iyear >= DateTime.MinValue.Year)
{
if (imonth >= 1 && imonth <= 12)
{
if (DateTime.DaysInMonth(iyear, imonth) >= iday && iday >= 1)
return new DateTime(iyear, imonth, iday);
}
}
return null;
}
protected DateTime? getDateTime(string dateStr)
{
Regex r = new Regex(#"^(\d\d)(\d\d)((\d\d)?\d\d)$");
Match m = r.Match(dateStr);
if (m.Success)
{
return getDateTimeFromParts(m.Groups[1].Value, m.Groups[2].Value, m.Groups[3].Value);
}
r = new Regex(#"^(\d?\d|\s\d|\s\s)[-](\d?\d|\s\s)[-]((\d\d)?\d\d|\s\s\s\s)$");
m = r.Match(dateStr);
if (m.Success)
{
return getDateTimeFromParts(m.Groups[1].Value, m.Groups[2].Value, m.Groups[3].Value);
}
return null;
}

Check if a datetime is in same week as other datetime

Let's say I have a list of dates in a table. Now I want to find all rows, which is in the same week as the date provided as an argument.
Let's say I have a table with:
2014-09-11
2014-09-12
2014-09-15
And I give this function the argument 2014-09-09, it has to look from monday->sunday, and realize that 09-11 and 09-12 is part of the week, but not 09-15.
How on earth to solve this?
I have thought on making a check on year, month and weeknumber, but you cannot guarantee that month is the same...
So how do you solve a problem like this?
DxCk's comment is valid. This solution will work even if the first or last week of the year cross two different years:
Check that the first day of the week for both dates fall on the same day.
Here is the code:
private bool DatesAreInTheSameWeek(DateTime date1, DateTime date2)
{
var cal = System.Globalization.DateTimeFormatInfo.CurrentInfo.Calendar;
var d1 = date1.Date.AddDays(-1 * (int)cal.GetDayOfWeek(date1));
var d2 = date2.Date.AddDays(-1 * (int)cal.GetDayOfWeek(date2));
return d1 == d2;
}
why not?
bool AreFallingInSameWeek(DateTime date1, DateTime date2)
{
return date1.AddDays(-(int)date1.DayOfWeek) == date2.AddDays(-(int)date2.DayOfWeek);
}
if you want to use any day other than Sunday as start of the week
bool AreFallingInSameWeek(DateTime date1, DateTime date2, DayOfWeek weekStartsOn)
{
return date1.AddDays(-GetOffsetedDayofWeek(date1.DayOfWeek, (int)weekStartsOn)) == date2.AddDays(-GetOffsetedDayofWeek(date2.DayOfWeek, (int)weekStartsOn));
}
int GetOffsetedDayofWeek(DayOfWeek dayOfWeek, int offsetBy)
{
return (((int)dayOfWeek - offsetBy + 7) % 7)
}
Check the DateTime.Year and Calendar.GetWeekOfYear(DateTime, ...). No need to check for the month.
EDIT: This is wrong but I can't delete it. See #Sparrow's answer below.
Use: public virtual int GetWeekOfYear(DateTime time,CalendarWeekRule rule,DayOfWeek firstDayOfWeek) of Calendar class
My requirement was to find DOBs falling on the current week. Hope this helps with your doubt. Basically the idea behind this code is as follows:
Change the DOB to current year birthday (eg; 24-02-1988 to 24-02-2018(current year).
Add a year, if the brithday week contains both dec and jan
Get the first day of today's week.
Get last day of today's week.
check if the current year birthday falls between first day and last day of today's week.
private bool DatesAreInTheSameWeek(DateTime birthday)
{
if (birthday == DateTime.MinValue)
{
return false;
}
else
{
var birtdayWithCurrentYear = new DateTime(DateTime.Today.Year, birthday.Month, birthday.Day);
if (birthday.Month == 1 && DateTime.Today.Month != 1)
{
birtdayWithCurrentYear = birtdayWithCurrentYear.AddYears(1);
}
DateTime firstDayInWeek = DateTime.Today.Date;
while (firstDayInWeek.DayOfWeek != CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
firstDayInWeek = firstDayInWeek.AddDays(-1);var lastDayInWeek = firstDayInWeek.AddDays(7);
return birtdayWithCurrentYear < lastDayInWeek && birtdayWithCurrentYear >= firstDayInWeek;
}
}
Since the accepted answer contains error as #DxCK mentioned in comment, here is my solution for this:
public static class DateExtensions
{
private static void Swap<T>(ref T one, ref T two)
{
var temp = one;
one = two;
two = temp;
}
public static bool IsFromSameWeek(this DateTime first, DateTime second, DayOfWeek firstDayOfWeek = DayOfWeek.Monday)
{
// sort dates
if (first > second)
{
Swap(ref first, ref second);
}
var daysDiff = (second - first).TotalDays;
if (daysDiff >= 7)
{
return false;
}
const int TotalDaysInWeek = 7;
var adjustedDayOfWeekFirst = (int)first.DayOfWeek + (first.DayOfWeek < firstDayOfWeek ? TotalDaysInWeek : 0);
var adjustedDayOfWeekSecond = (int)second.DayOfWeek + (second.DayOfWeek < firstDayOfWeek ? TotalDaysInWeek : 0);
return adjustedDayOfWeekSecond >= adjustedDayOfWeekFirst;
}
}
Also here is link to another correct solution with slightly different approach.
Find start and end dates for the first date's week. Then check if the second date is between those two.
public static bool DateInsideOneWeek(DateTime date1, DateTime date2)
{
DayOfWeek firstDayOfWeek = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
DateTime startDateOfWeek = date1.Date;
while(startDateOfWeek.DayOfWeek != firstWeekDay)
{ startDateOfWeek = startDateOfWeek.AddDays(-1d); }
DateTime endDateOfWeek = startDateOfWeek.AddDays(6d);
return date2 >= startDateOfWeek && date2 <= endDateOfWeek;
}
If you don't want to use the Calendar class you can use this function:
public static int WeekOfYear(DateTime dt)
{
int startDays = 0;
// first day of the year
DateTime firstJanuary = new DateTime(dt.Year, 1, 1);
if (firstJanuary.DayOfWeek == DayOfWeek.Tuesday)
{
startDays = 1;
}
else if (firstJanuary.DayOfWeek == DayOfWeek.Wednesday)
{
startDays = 2;
}
else if (firstJanuary.DayOfWeek == DayOfWeek.Thursday)
{
startDays = 3;
}
else if (firstJanuary.DayOfWeek == DayOfWeek.Friday)
{
startDays = 4;
}
else if (firstJanuary.DayOfWeek == DayOfWeek.Saturday)
{
startDays = 5;
}
else if (firstJanuary.DayOfWeek == DayOfWeek.Sunday)
{
startDays = 6;
}
if (DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek == DayOfWeek.Sunday)
{
startDays++;
startDays = startDays % 7;
}
return ((dt.DayOfYear + startDays - 1) / 7) + 1;
}
Accepted answer doesn't work for a french calendar and when the dates are 03/10/2022 and 09/10/2022.
This worked for me :
public static partial class DateTimeExtensions
{
public static DateTime FirstDayOfWeek(this DateTime dt)
{
var culture = System.Threading.Thread.CurrentThread.CurrentCulture;
var diff = dt.DayOfWeek - culture.DateTimeFormat.FirstDayOfWeek;
if (diff < 0)
{
diff += 7;
}
return dt.AddDays(-diff).Date;
}
public static DateTime LastDayOfWeek(this DateTime dt) =>
dt.FirstDayOfWeek().AddDays(6);
public static DateTime FirstDayOfMonth(this DateTime dt) =>
new DateTime(dt.Year, dt.Month, 1);
public static DateTime LastDayOfMonth(this DateTime dt) =>
dt.FirstDayOfMonth().AddMonths(1).AddDays(-1);
public static DateTime FirstDayOfNextMonth(this DateTime dt) =>
dt.FirstDayOfMonth().AddMonths(1);
public static int GetWeeekNumber(this DateTime dt)
{
CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture;
Calendar myCal = culture.Calendar;
// Gets the DTFI properties required by GetWeekOfYear.
CalendarWeekRule myCWR = culture.DateTimeFormat.CalendarWeekRule;
DayOfWeek myFirstDOW = culture.DateTimeFormat.FirstDayOfWeek;
return myCal.GetWeekOfYear(dt, myCWR, myFirstDOW);
}
public static bool IsInTheSameWeek(this DateTime date1, DateTime date2)
{
return date1.GetWeeekNumber() == date2.GetWeeekNumber();
}
}
Usage :
item.Week.IsInTheSameWeek(Week)

how to get the total selected days from 2 calendars in asp.net

just like in my questions, i have 2 calendars to be selected by users, and i would like to get the total selected days and be displayed in label.
users have to select the start date in lstartdate calendar and end date in lenddate calendar.
private void ValidateDate()
{
if (lstartdate.Text == "" || lenddate.Text == "")
{
lwarndate.Visible = true;
lwarndate.Text = "Dates required";
}
if (lstartdate.Text != "" || lenddate.Text != "")
{
if (cstart.SelectedDate > cend.SelectedDate)
{
lwarndate.Visible = true;
lwarndate.Text = "Start date must be earlier than end date!";
}
if (cstart.SelectedDate <= cend.SelectedDate)
{
lwarndate.Visible = false;
}
if (cend.SelectedDate != null && cstart.SelectedDate != null)
{
Double Value;
if (cend.SelectedDate >= cstart.SelectedDate)
Value = (cend.SelectedDate - cstart.SelectedDate).TotalDays;
else
Value = (cend.SelectedDate - cstart.SelectedDate).TotalDays;
total.Text = // ?
}
}
}
im not sure if the code arrangements are correct or not. do help and tq :)
TRY LIKE THIS
DateTime DtF = ceFromDate.SelectedDate.Value;
DateTime D1T = ceToDate.SelectedDate.Value;
double dd = (DtF - D1T).TotalDays;
total.Text = dd.ToString();
Here is simple way to get different between two dates
class Program
{
static void Main(string[] args)
{
System.DateTime dtTodayNoon = new System.DateTime(2006, 9, 13, 12, 0, 0);
System.DateTime dtTodayMidnight = new System.DateTime(2006, 9, 13, 0, 0, 0);
System.TimeSpan diffResult = dtTodayNoon.Subtract(dtYestMidnight);
Console.WriteLine("Yesterday Midnight - Today Noon = " + diffResult.Days);
Console.WriteLine("Yesterday Midnight - Today Noon = " + diffResult.TotalDays);
Console.ReadLine();
}
}
Source
you need to implement it yourself..
Convert the difference between the two dates into a TimeSpan, then get the amount of Days of that TimeSpan and set this as your text-value.
private void ValidateDate()
{
if (lstartdate.Text == "" || lenddate.Text == "")
{
lwarndate.Visible = true;
lwarndate.Text = "Dates required";
}
if (lstartdate.Text != "" || lenddate.Text != "")
{
if (cstart.SelectedDate > cend.SelectedDate)
{
lwarndate.Visible = true;
lwarndate.Text = "Start date must be earlier than end date!";
}else{
lwarndate.Visible = false;
}
if (cend.SelectedDate != null && cstart.SelectedDate != null)
{
TimeSpan duration = DateTime.Parse(cend.SelectedDate ).Subtract(DateTime.Parse(cstart.SelectedDate ));
total.Text = duration.Days.ToString();
}
}
}

Categories

Resources