Check open and close time in 3 different cases - c#

I have 2 variables
DateTime closingTime
TimeSpan diffTime = DateTime.Now.Subtract(endtime);
I would like to check 3 cases:
the store is open n hours and n minutes
the store is open n minutes
the store is closed
my code:
if(diffTime.Minutes > 0 || diffTime.Hours == 0 )
_timeLeft = "Noch " + diffTime.Minutes.ToString() + " Minuten geöffnet";
if (diffTime.Hours > 0)
_timeLeft = "Noch " + diffTime.Hours.ToString() + " Stunden und " + diffTime.Minutes.ToString() + " Minuten geöffnet";
else
//Der Markt ist derzeit geschlossen,
_timeLeft = "Feierabend!";
Is it possible without the "openingTime"?

No way to proof all 3 cases just with closingTime and DateTime.Now
if ((DateTime.Now > openingTime) && (DateTime.Now < closingTime) && diffTime.Hours == 0)
_timeLeft = "Noch " + diffTime.Minutes.ToString() + " Minuten geöffnet";
else if ((DateTime.Now > openingTime) && (DateTime.Now < closingTime))
_timeLeft = "Noch " + diffTime.Hours.ToString() + " Stunden und " + diffTime.Minutes.ToString() + " Minuten geöffnet";
else
//Der Markt ist derzeit geschlossen,
_timeLeft = "Feierabend!";

Related

Calculate Daylight Saving Time in C#

How do you calculate Daylight Savings Time in C# with DateTime.Now? DST starts on the Second
Sunday in March. And ends on the first Sunday in November. These can be calculated thru the DayOfWeek in DateTime.
DayOfWeek dow;
string p = "3" + "/" + dy.ToString() + "/" + yr.ToString() + " " + "3" + ":" + mn.ToString() + ":" + sc.ToString();
DateTime start = DateTime.Parse(p);
p = "11" + "/" + dy.ToString() + "/" + yr.ToString() + " " + "1" + ":" + mn.ToString() + ":" + sc.ToString();
DateTime end = DateTime.Parse(p);
DateTime current;
for (dys = 1; dys <= 17; dys++)
{
p = "3" + "/" + dys.ToString() + "/" + yr.ToString() + " " + "3" + ":" + mn.ToString() + ":" + sc.ToString();
current = DateTime.Parse(p);
dow = current.DayOfWeek;
if ((mo == 3) && (aaa == 0) && (dow == DayOfWeek.Sunday))
{
aaa = 1;
}
if ((aaa == 1) && (dow == DayOfWeek.Sunday))
{
start = DateTime.Parse(p);
aaa = 2;
}
}
for (dye = 1; dye <= 14; dye++)
{
p = "11" + "/" + dye.ToString() + "/" + yr.ToString() + " " + "1" + ":" + mn.ToString() + ":" + sc.ToString();
current = DateTime.Parse(p);
dow = current.DayOfWeek;
if ((mo == 11) && (bbb == 0) && (dow == DayOfWeek.Sunday))
{
bbb = 1;
end = DateTime.Parse(p);
}
}
if ((start >= DateTime.Now) && (end <= DateTime.Now))
{
dsts = 0;
}
else
{
dsts = 1;
}
You can check these microsoft implementations. They already handle timezones and daylight saving time conversions. We do not need to implement them.
You need DateTimeOffset and TimeZoneInfo classes to deal with all these.
Always work with DateTimeOffset class instead of DateTime when dealing with timezones. https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset?view=net-6.0
link1: https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo?view=net-6.0
Convert time from one timezone to other https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo.converttime?view=net-6.0
Something like below
DateTimeOffset thisTime = DateTimeOffset.Now;
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
bool isDaylight = tzi.IsDaylightSavingTime(thisTime);
DateTimeOffset timeInUtcTimeZone = TimeZoneInfo.ConvertTimeToUtc(thisTime);
DateTimeOffset timeInPstTimeZone = TimeZoneInfo.ConvertTimeToUtc(thisTime, tzi);
Similarly you can convert time from any timezone to any other timezone. And also the comparisons (Equals, greater than, less than) across the timezone will work well and handled by the framework.

How to refine this code, in terms of performance and readability?

My Desired output :
if the difference is less than a minute the result should be "Updated just now" and if the difference is than greater than a minute and less than an hour then the result should be "Updated X mintues ago"
Code:
string result = "";
if (difference.Days == 0)
{
if (difference.Hours == 0)
{
if (difference.Minutes == 0)
{
result = "Updated just now";
}
else
{
result = "Updated " + difference.Minutes.ToString() + " minutes ago";
}
}
else
{
result = "Updated " + difference.Hours.ToString() + " hours ago";
}
}
else
{
result = "Updated " + difference.Days.ToString() + " days ago";
}
string format = "Updated {0} {1} ago";
string result = "Updated just now";
// this test can be deleted
if(difference.TotalSeconds > 60)
{
if(difference.Days != 0)
result = string.Format(format, difference.Days, "days");
else if (difference.Hours != 0)
result = string.Format(format, difference.Hours, "Hours");
else if (difference.Minutes != 0)
result = string.Format(format, difference.Minutes, "Minutes");
}
so that the result is cleaner, replace "days" by difference.Days > 1 ? "Days" : "Day"
the purpose of the format string, is to avoid memory leak and to allow user change text format easily and for multilang
string result = "Updated ";
if (difference.Days != 0)
result += difference.Days.ToString() + " days ago";
else if (difference.Hours != 0)
result += difference.Hours.ToString() + " hours ago";
else if (difference.Minutes != 0)
result += difference.Minutes.ToString() + " minutes ago";
else
result += "just now";

Refactoring else if statement that returns current week from Wednesday

I am quite concerned about whether or not the code in CurrentRentWeek.cs is future-proof, is it good practice to have this many else if statements? If not, what would be the best way to refactor it?
MainWindow.Xaml.cs
public MainWindow()
{
InitializeComponent();
// Set current rent week
var datecheckObject = new CurrentRentWeek();
CurrentRentWeekTextBlock.Text = datecheckObject.DateCheck(CurrentRentWeekTextBlock.Text);
}
CurrentRentWeek.cs
public string DateCheck(string rentWeek)
{
if (_today.DayOfWeek == DayOfWeek.Monday)
{
_cRentWeekStart = _today.AddDays(-5);
_cRentWeekEnd = _today.AddDays(2);
rentWeek = "Current Rent Week: " + _cRentWeekStart.ToString("dd/MM/yyyy") + " - " +
_cRentWeekEnd.ToString("dd/MM/yyyy");
}
else if (_today.DayOfWeek == DayOfWeek.Tuesday)
{
_cRentWeekStart = _today.AddDays(-6);
_cRentWeekEnd = _today.AddDays(1);
rentWeek = "Current Rent Week: " + _cRentWeekStart.ToString("dd/MM/yyyy") + " - " +
_cRentWeekEnd.ToString("dd/MM/yyyy");
}
else if (_today.DayOfWeek == DayOfWeek.Wednesday)
{
_cRentWeekStart = _today.AddDays(0);
_cRentWeekEnd = _today.AddDays(7);
rentWeek = "Current Rent Week: " + _cRentWeekStart.ToString("dd/MM/yyyy") + " - " +
_cRentWeekEnd.ToString("dd/MM/yyyy");
}
else if (_today.DayOfWeek == DayOfWeek.Thursday)
{
_cRentWeekStart = _today.AddDays(-1);
_cRentWeekEnd = _today.AddDays(6);
rentWeek = "Current Rent Week: " + _cRentWeekStart.ToString("dd/MM/yyyy") + " - " +
_cRentWeekEnd.ToString("dd/MM/yyyy");
}
else if (_today.DayOfWeek == DayOfWeek.Friday)
{
_cRentWeekStart = _today.AddDays(-2);
_cRentWeekEnd = _today.AddDays(5);
rentWeek = "Current Rent Week: " + _cRentWeekStart.ToString("dd/MM/yyyy") + " - " +
_cRentWeekEnd.ToString("dd/MM/yyyy");
}
else if (_today.DayOfWeek == DayOfWeek.Saturday)
{
_cRentWeekStart = _today.AddDays(-3);
_cRentWeekEnd = _today.AddDays(4);
rentWeek = "Current Rent Week: " + _cRentWeekStart.ToString("dd/MM/yyyy") + " - " +
_cRentWeekEnd.ToString("dd/MM/yyyy");
}
else if (_today.DayOfWeek == DayOfWeek.Sunday)
{
_cRentWeekStart = _today.AddDays(-4);
_cRentWeekEnd = _today.AddDays(3);
rentWeek = "Current Rent Week: " + _cRentWeekStart.ToString("dd/MM/yyyy") + " - " +
_cRentWeekEnd.ToString("dd/MM/yyyy");
}
else
{
rentWeek = "";
}
return rentWeek;
}
You can start out with a generalized function to get the start of the week for any give date:
public static DateTime StartOfWeek(DateTime date)
{
while (date.DayOfWeek != DayOfWeek.Wednesday)
date = date.AddDays(-1);
return date;
}
Then you can simply call that method, add a fixed number of days to get to the end of the week, and create the string for those dates:
public string DateCheck()
{
var startOfWeek = StartOfWeek(_today);
var endOfWeek = startOfWeek.AddDays(7);
return string.Format("Current Rent Week: {0} - {1}",
startOfWeek.ToString("dd/MM/yyyy"),
endOfWeek.ToString("dd/MM/yyyy"));
}
You want that Wednesday is the beginning of the week? You can use this:
int daysDiff = (int)_today.DayOfWeek - (int)DayOfWeek.Wednesday;
if (daysDiff >= 0)
_cRentWeekStart = _today.AddDays(-daysDiff);
else
_cRentWeekStart = _today.AddDays(-(7 + daysDiff));
_cRentWeekEnd = _cRentWeekStart.AddDays(7);
This will return the last week's wednesday if today is "less" than wednesday which seems to be desired.
I think a switch statement would be much clearer for your case and give time savings but I doubt thats an issue.
switch (_today.DayOfWeek)
{
case DayOfWeek.Monday:
_cRentWeekStart = _today.AddDays(-5);
_cRentWeekEnd = _today.AddDays(2);
rentWeek = "Current Rent Week: " + _cRentWeekStart.ToString("dd/MM/yyyy") + " - " +_cRentWeekEnd.ToString("dd/MM/yyyy");
break;
case DayOfWeek.Tuesday:
//...
break;
//rest of cases
}

Time elapsed between two dates

I want to find the exact time elapsed between two dates with a condition that if any value is "0" its measurement units should disappear. for example if hours and minutes are o than the elapsed time should come like 1 day 40 seconds not like 1 day 0 hours 0 minutes 40 seconds.
TimeSpan elapsed = completdDate.Subtract(insertdDate);
int daysEl= elapsed.Days;
int hrsEl= elapsed.Hours;
int minsEl = elapsed.Minutes;
int secEl = elapsed.Seconds;
string totalTime = string.Empty;
string days = string.Empty;
string hours = string.Empty;
string mins = string.Empty;
string secs = string.Empty;
if (daysEl == 0 )
days = days.Replace(daysEl.ToString() , "");
else
days = daysEl.ToString();
if (hrsEl==0)
hours = hours.Replace(hrsEl.ToString() , "");
else
hours = hrsEl.ToString();
if (minsEl == 0)
mins = mins.Replace(minsEl.ToString(), "");
else
mins = minsEl.ToString();
if (secEl == 0)
secs = secs.Replace(secEl.ToString(), "");
else
secs = secEl.ToString();
totalTime = days + "days"
+ hours + "hours"
+ mins + "minutes"
+ secs + "seconds";
********************************Output*****************************
You can get rid of the intermediate strings and if statements:
totalTime =
(daysEl == 0 ? "" : (daysEl + " days "))
+ (hoursEl == 0 ? "" : (hoursEl + " hours "))
+ (minsEl == 0 ? "" : (minsEl + " minutes "))
+ (secsEl == 0 ? "" : (secsEl + " seconds "));
If you want to omit zero values, you're more likely looking at a formatting issue, not a calculation one, and it might be easier to use a StringBuilder.
var sb = new StringBuilder();
if (elapsed.Days != 0)
sb.AppendFormat("{0} days ", elapsed.Days);
if (elapsed.Hours != 0)
sb.AppendFormat("{0} hours ", elapsed.Hours);
if (elapsed.Minutes != 0)
sb.AppendFormat("{0} minutes ", elapsed.Minutes);
if (elapsed.Seconds != 0)
sb.AppendFormat("{0} seconds ", elapsed.Seconds);
if (sb.Length == 0)
return "instant!";
// get rid of the last space in there!
return sb.ToString().Substring(0,sb.Length-1);
By using a format, you're able to more succinctly bind the value with the units (ie "14 seconds") and thus put the whole portion into an if statement, bypassing the section entirely if it's zero.
void Main()
{
TimeSpan elapsed = DateTime.Now - DateTime.Now.AddDays(-1);
int daysEl= elapsed.Days;
int hrsEl= elapsed.Hours;
int minsEl = elapsed.Minutes;
int secEl = elapsed.Seconds;
var sb = new StringBuilder();
if (daysEl != 0 )
sb.Append(daysEl + " days ");
if (hrsEl != 0)
sb.Append(hrsEl + " hours ");
if (minsEl != 0)
sb.Append(minsEl + " mins ");
if (secEl != 0)
sb.Append(secEl + " secs ");
string totalTime = sb.ToString();
Console.WriteLine (totalTime);
}

TimeSpan to Localized String in C#

Is there an easy way (maybe built in solution) to convert TimeSpan to localized string? For example new TimeSpan(3, 5, 0); would be converted to 3 hours, 5minutes (just in polish language).
I can of course create my own extension:
public static string ConvertToReadable(this TimeSpan timeSpan) {
int hours = timeSpan.Hours;
int minutes = timeSpan.Minutes;
int days = timeSpan.Days;
if (days > 0) {
return days + " dni " + hours + " godzin " + minutes + " minut";
} else {
return hours + " godzin " + minutes + " minut";
}
}
But this gets complicated if i want to have proper grammar involved.
The easiest way to do this is to put the format string in a localized resource, and translate appropriately for each supported language.
Unfortunately there's no standard way to do such thing.
Nobody seems to agree in what should be the proper way.... :-\
And people like us that write software for multiple languages suffer.
I do not think this is possible. What you can do is something like this:
public static string ConvertToReadable(this TimeSpan timeSpan) {
return string.Format("{0} {1} {2} {3} {4} {5}",
timeSpan.Days, (timeSpan.Days > 1 || timeSpan.Days == 0) ? "days" : "day",
timeSpan.Hours, (timeSpan.Hours > 1 || timeSpan.Hours == 0) ? "hours" : "hour",
timeSpan.Minutes, (timeSpan.Minutes > 1 || timeSpan.Minutes == 0) ? "minutes" : "minute");
}
Here's the code that I've cooked out:
public static string ConvertToReadable(this TimeSpan timeSpan) {
int hours = timeSpan.Hours;
int minutes = timeSpan.Minutes;
int days = timeSpan.Days;
string hoursType;
string minutesType;
string daysType;
switch (minutes) {
case 1:
minutesType = "minuta";
break;
case 2:
case 3:
case 4:
minutesType = "minuty";
break;
default:
minutesType = "minut";
break;
}
switch (hours) {
case 1:
hoursType = "godzina";
break;
case 2:
case 3:
case 4:
hoursType = "godziny";
break;
default:
hoursType = "godzin";
break;
}
switch (days) {
case 1:
daysType = "dzień";
break;
default:
daysType = "dni";
break;
}
if (days > 0) {
return days + " " + daysType + " " + hours + " " + hoursType + " " + minutes + " " + minutesType;
}
return hours + " " + hoursType + " " + minutes + " " + minutesType;
}

Categories