Check is time inside a range - c#

Im trying to perform a check is entered time inside specified time interval but Im stuck... I have one main block and another class which perform the check is the entered time inside the interval but I keep getting "No overload for method 'IsBetween' takes 0 arguments" when I try to call the method and get simple bool true or false, I know that solution is probably really simple but I just cant figure it out... :
static void Main()
{
var currentTime = Console.ReadLine();
DateTime now = Convert.ToDateTime(currentTime);
var dateNow = DateTime.Now;
var startTime = new DateTime(dateNow.Year, dateNow.Month, dateNow.Day, 13, 0, 0);
var endTime = new DateTime(dateNow.Year, dateNow.Month, dateNow.Day, 3, 0, 0);
}
This is my class for check :
public static class TimeExtensions
{
public static bool IsBetween(this DateTime now, DateTime startTime, DateTime endTime)
{
if (now.TimeOfDay == startTime.TimeOfDay) return true;
if (now.TimeOfDay == endTime.TimeOfDay) return true;
if (startTime.TimeOfDay <= endTime.TimeOfDay)
return (now.TimeOfDay >= startTime.TimeOfDay && now.TimeOfDay <= endTime.TimeOfDay);
else
return !(now.TimeOfDay >= endTime.TimeOfDay && now.TimeOfDay <= startTime.TimeOfDay);
}
}

The error suggests you are calling IsBetween like:
bool b = now.IsBetween();
but you need to provide the start and end times:
bool b = now.IsBetween(startTime, endTime);

Related

Get time left until sunday 9:30 pm

What I want to do is basically in the question title.
This is what I've tried so far, unsuccessfully.
Note that I haven't implemented exact hour and minute yet (9:30 pm).
It actually seems to always return a value between 00:00:59 and 00:00:01 for some reason
DateTime nextSunday = DateTime.Today.AddDays(((int)DayOfWeek.Sunday - (int)DateTime.Today.DayOfWeek + 7) % 7) + new TimeSpan(21, 30, 0);
TimeSpan untilNextSunday = nextSunday - DateTime.Now;
await ReplyAsync($"It is in **{TimeSpan.FromSeconds(untilNextSunday.Seconds)}**");
Which equals to
var today = DateTime.Today;
var daysUntilSunday = ((int)DayOfWeek.Sunday - (int)today.DayOfWeek + 7) % 7;
var nextSunday = today.AddDays(daysUntilSunday);
var ts = new TimeSpan(21, 30, 0);
nextSunday = nextSunday.Date + ts;
TimeSpan untilNextSunday = nextSunday - DateTime.Now;
If possible, I'd also like to use Paris TimeZone.
I tend to find all of the DateTime.Today.AddDays(((int)DayOfWeek.Sunday - (int)DateTime.Today.DayOfWeek + 7) % 7) + new TimeSpan(21, 30, 0) arithmetic quite confusing. Instead I try to go with a more iterative approach that can be clearly reasoned about.
Try this:
public static DateTime GetNextDateTime(DateTime now, DayOfWeek targetDay, TimeSpan targetTime)
{
DateTime target = now.Date.Add(targetTime);
while (target < now || target.DayOfWeek != targetDay)
{
target = target.AddDays(1.0);
}
return target;
}
Now you can use it like this:
DateTime now = DateTime.Now;
DateTime target = GetNextDateTime(DateTime.Now, DayOfWeek.Sunday, new TimeSpan(21, 30, 0));
TimeSpan untilNextSunday = target.Subtract(now);
Here's an example using Noda Time, including time zone handling. It doesn't attempt to handle "interesting" situations where (say) you ask for the next 1:30am, and it's already 1:45am but the clock goes back at 2am - in which case the right answer is really "45 minutes" but this code will give you a week instead.
using System;
using NodaTime;
class Test
{
static void Main()
{
var duration = GetDurationToNext(
IsoDayOfWeek.Sunday, new LocalTime(21, 30),
DateTimeZoneProviders.Tzdb["Europe/Paris"],
SystemClock.Instance);
Console.WriteLine($"Duration: {duration}");
}
static Duration GetDurationToNext(
IsoDayOfWeek dayOfWeek,
LocalTime timeOfDay,
DateTimeZone zone,
IClock clock) // Or just take an instant
{
var now = clock.GetCurrentInstant();
var localNow = now.InZone(zone).LocalDateTime;
var localNext = localNow
.Date.With(DateAdjusters.NextOrSame(dayOfWeek))
.At(timeOfDay);
// Handle "we're already on the right day-of-week, but
// later in the day"
if (localNext <= localNow)
{
localNext = localNext.PlusWeeks(1);
}
var zonedNext = localNext.InZoneLeniently(zone);
var instantNext = zonedNext.ToInstant();
return instantNext - now;
}
}

How made var DateTime global variable

How to make newTime as a global variable?
It should be added 30 minutes in time and use it in a condition. It is necessary to make var newTime as global var.
if (timerCheck == 0)
{
var today = DateTime.Now;
var interval = new TimeSpan(00, 30, 00);
var newTime = today + interval;
timerCheck = 1;
}
if (timerCheck == 1)
{
var today = DateTime.Now;
if (today >= newTime)
{
You can do it like this
public static class GlobalVariables
{
public static DateTime NewTime { get; set; }
}
Then call it like this:
if (today >= GlobalVariables.NewTime)
Just move it outside if.
I don't test it, but It might work.
DateTime newTime;
if (timerCheck == 0)
{
var today = DateTime.Now;
var interval = new TimeSpan(00, 30, 00);
newTime = today + interval;
timerCheck = 1;
}
if (timerCheck == 1)
{
if (newTime.Equals(default(DateTime)) return; // don't sure is it required or not
var today = DateTime.Now;
if (today >= newTime)
{
Well i think you should put it outside the body of If first as a variable then use it in the condition.

What is the C# Syntax for something like date.IsWithIn(x months).Of(Comparison Date)?

The title is a bit whacky, but that's the question. I'm using C#. I'm trying to come up with several DateTime extension methods. While thinking about it, I wondered what syntax it would take for me to write the code as follows:
DateTime comparisonDate = DateTime.Now.AddMonths(-3);
if( DateTime.Now.IsWithIn(3).Of(comparisonDate) ) ....
I've written extension methods before, but I'm not sure how composing something like this would work. The "IsWithIn" would be one method...but would this return an Expression and the "Of" method would be an extension method of the Expression class?
EDIT 1
Still thinking about this. I'm wondering if this approach, though readable, is over complicating things. My first revision just tweaks #Wai Ha Lee's is to the DateTimeExtensions class. I'll refactor this and keep iterating. This screams strategy pattern but I haven't fit that into it yet. There's also no "Of" method now and the method name seems to make sense...today at least. A month from now? I'm not sure.
I also thought of another way I'd like to be able to write this code. I guess I'm still dreaming, but here that goes:
date.IsWithIn(1).Days().Of(comparisonDate);
date.IsWithIn(1).Months().Of(comparisonDate);
date.IsWithIn(1).Years().Of(comparisonDate);
But that aside, here's the revision I have that's merely a DateTime extension without the method name chaining.
public class Program
{
static void Main(string[] args)
{
DateTime now = DateTime.Now;
DateTime past = new DateTime(2015, 1, 15);
DateTime future = new DateTime(2015, 3, 15);
DateTime comparison = now.AddDays(-2);
int interval = 1;
DateInterval di = DateInterval.Days;
Console.WriteLine(
string.Format("Now, {0}, is with in {1} {2} of {3} is {4}",
now.ToShortDateString(),
interval.ToString(),
di.ToString(),
comparison.ToShortDateString(),
now.IsDateWithinXRangeOfAnotherDate(interval, di, comparison).ToString())
);
Console.ReadLine();
}
}
public enum DateInterval
{
Days,
Months,
Years
}
public static class DateTimeExtensions
{
public static bool IsDateWithinXRangeOfAnotherDate(this DateTime date, int interval, DateInterval dateInterval, DateTime comparisonDate)
{
DateTime _min = comparisonDate;
DateTime _max = comparisonDate;
switch(dateInterval)
{
case DateInterval.Days:
_min = _min.AddDays(-interval);
_max = _max.AddDays(interval);
Console.WriteLine(
string.Format("Min Date is {0} Max Date is {1}",
_min.ToShortDateString(),
_max.ToShortDateString()));
break;
case DateInterval.Months:
_min = _min.AddMonths(-interval);
_max = _max.AddMonths(interval);
Console.WriteLine(
string.Format("Min Date is {0} Max Date is {1}",
_min.ToShortDateString(),
_max.ToShortDateString()));
break;
case DateInterval.Years:
_min = _min.AddYears(-interval);
_max = _max.AddYears(interval);
Console.WriteLine(
string.Format("Min Date is {0} Max Date is {1}",
_min.ToShortDateString(),
_max.ToShortDateString()));
break;
}
return _min <= date && date <= _max;
}
}
EDIT 2
Revising:
date.IsWithIn(1).Days().Of(comparisonDate);
date.IsWithIn(1).Months().Of(comparisonDate);
date.IsWithIn(1).Years().Of(comparisonDate);
to
date.IsWithIn(1.Days()).Of(comparisonDate);
date.IsWithIn(1.Months()).Of(comparisonDate);
date.IsWithIn(1.Years()).Of(comparisonDate);
After looking at FluentTime for a bit, I noticed the author used several methods and classes I didn't even know existed. For one, he used the TimeSpan.FromDays method. He may have overloaded the + symbol because, at another point in the code, he just adds the timespan to a date. Given how TimeSpans work, I may only be able to implement the 1.Days() portion...and I think that's all I really need.
Will keep playing around with all this until I get it figured out. I could just use the FluentTime library, but it's overkill for what I need this for as the library handles time as well. I'm strictly interested in date range comparisons. Methods like After(), Before(), IsBetween(), IsWithIn. I've implemented the first 3 already. This question pivots on answering the last one.
EDIT 3 - SOLVED!
This question has become more an exercise in code than practicality. Ultimately, Jon Skeet was right about having to create a custom type. The solution breaks down to this summary:
A custom class: FluentDateTime was created
3 int Extension methods - Days, Months, Years. These each return a FluentDateTime class.
1 DateTime extension method - IsWithIn that takes a FluentDateTime parameter
I want to emphasize that this is a lot of buck for very little bang...but, regardless, here's the code.
public class FluentDateTime
{
public enum DateInterval
{
Days,
Months,
Years
}
private DateTime _lowDate;
private DateTime _highDate;
public DateTime BaseDate { get; set; }
public DateInterval Interval { get; set; }
public int Increment { get; set; }
public bool Of(DateTime dt)
{
_lowDate = dt;
_highDate = dt;
if(this.Interval == DateInterval.Days)
{
_lowDate = _lowDate.AddDays(-this.Increment);
_highDate = _highDate.AddDays(this.Increment);
}
else if (this.Interval == DateInterval.Months)
{
_lowDate = _lowDate.AddMonths(-this.Increment);
_highDate = _highDate.AddMonths(this.Increment);
}
else
{
_lowDate = _lowDate.AddYears(-this.Increment);
_highDate = _highDate.AddYears(this.Increment);
}
Console.WriteLine(
string.Format("{0} <= {1} <= {2}", _lowDate.ToShortDateString(), BaseDate.ToShortDateString(), _highDate.ToShortDateString()
));
return (_lowDate < BaseDate && BaseDate < _highDate) || (_lowDate.Equals(BaseDate) || _highDate.Equals(BaseDate) );
}
}
// DATETIME EXTENSION
public static FluentDateTime IsWithIn(this DateTime date, FluentDateTime fdtParams)
{
fdtParams.BaseDate = date;
return fdtParams;
}
//INT EXTENSIONS
public static FluentDateTime Days(this int inc)
{
FluentDateTime fdt = new FluentDateTime();
fdt.Interval = FluentDateTime.DateInterval.Days;
fdt.Increment = inc;
return fdt;
}
public static FluentDateTime Months(this int inc)
{
FluentDateTime fdt = new FluentDateTime();
fdt.Interval = FluentDateTime.DateInterval.Months;
fdt.Increment = inc;
return fdt;
}
public static FluentDateTime Years(this int inc)
{
FluentDateTime fdt = new FluentDateTime();
fdt.Interval = FluentDateTime.DateInterval.Years;
fdt.Increment = inc;
return fdt;
}
//TEST PROGRAM
DateTime testDate1 = new DateTime(2015, 3, 3);
DateTime testDate2 = new DateTime(2015, 3, 4);
Console.WriteLine(
string.Format("{0} is within 5 days of {1}? {2} (should be true)",
testDate1.ToShortDateString(), testDate2.ToShortDateString(), testDate1.IsWithIn(5.Days()).Of(testDate2)
));
testDate1 = new DateTime(2015, 3, 1);
testDate2 = new DateTime(2015, 3, 7);
Console.WriteLine(
string.Format("{0} is within 3 days of {1}? {2} (should be false)",
testDate1.ToShortDateString(), testDate2.ToShortDateString(), testDate1.IsWithIn(3.Days()).Of(testDate2)
));
testDate1 = new DateTime(2015, 3, 3);
testDate2 = new DateTime(2015, 4, 1);
Console.WriteLine(
string.Format("{0} is within 1 month of {1}? {2} (should be true)",
testDate1.ToShortDateString(), testDate2.ToShortDateString(), testDate1.IsWithIn(1.Months()).Of(testDate2)
));
testDate1 = new DateTime(2015, 3, 3);
testDate2 = new DateTime(2015, 6, 1);
Console.WriteLine(
string.Format("{0} is within 2 month of {1}? {2} (should be false)",
testDate1.ToShortDateString(), testDate2.ToShortDateString(), testDate1.IsWithIn(2.Months()).Of(testDate2)
));
IsWithin would have to return some sort of type representing a range of values, remembering the "centre" and the range size. Now Of could be an extension method of that, or could easily be a normal instance method, given that you'd be writing the type yourself.
Note that 3 isn't clear in terms of being 3 days, 3 hours or something else. You should work out how you want to specify that. You could take a TimeSpan instead of just an int, or have separate IsWithinDays, IsWithinHours etc methods.
A few things:
I assume that within {some time} of means {some time} either side of - if it just refers to after, the code is much simpler. Keeping my assumption means that .IsWithin(x).Of is commutative, i.e. a.IsWithin(x).Of(b) == b.IsWithin(x).Of(a).
DateTimeRange takes a Func<DateTime, int, DateTime> to avoid duplicated code (though there'd not be a range for that if my assumption a
I don't use TimeSpan because
The largest unit of time that the TimeSpan structure uses to measure duration is a day.
Without hyperbole, this is the worst thing ever, and I hate myself a little for posting this. I would never write code like this in a professional context. I've only done this to (almost) satisfy #jason's requirements (I renamed IsWithIn to IsWithin).
Usage
public static void Main()
{
var now = DateTime.Now;
var comparisonDate = now.AddMonths(-2);
bool within1Month = now.IsWithin(months: 1).Of(comparisonDate); // false
bool within2Months = now.IsWithin(months: 2).Of(comparisonDate); // true
bool within3Months = now.IsWithin(months: 3).Of(comparisonDate); // true
}
DateTimeExtensions:
public static class DateTimeExtensions
{
/// <summary>
/// <para>Specify exactly one of milliseconds, seconds, minutes, hours, days, months, or years.</para>
/// <para>Uses the first nonzero argument in the order specified.</para>
/// </summary>
public static DateTimeRange IsWithin(
this DateTime dateTime,
int milliseconds = 0, int seconds = 0, int minutes = 0, int hours = 0,
int days = 0, int months = 0, int years = 0)
{
if ( milliseconds != 0 )
return new DateTimeRange(dateTime, (_dateTime, _value) => _dateTime.AddMilliseconds(_value), milliseconds);
if ( seconds != 0 )
return new DateTimeRange(dateTime, (_dateTime, _value) => _dateTime.AddSeconds(_value), seconds);
if ( minutes != 0 )
return new DateTimeRange(dateTime, (_dateTime, _value) => _dateTime.AddMinutes(_value), minutes);
if ( hours != 0 )
return new DateTimeRange(dateTime, (_dateTime, _value) => _dateTime.AddHours(_value), hours);
if ( days != 0 )
return new DateTimeRange(dateTime, (_dateTime, _value) => _dateTime.AddDays(_value), days);
if ( months != 0 )
return new DateTimeRange(dateTime, (_dateTime, _value) => _dateTime.AddMonths(_value), months);
if ( years != 0 )
return new DateTimeRange(dateTime, (_dateTime, _value) => _dateTime.AddYears(_value), years);
throw new ArgumentException("At least one value must be nonzero");
}
}
DateTimeRange:
/// <summary>
/// Represents a range between two DateTime values
/// </summary>
public struct DateTimeRange
{
private DateTime _min;
private DateTime _max;
public DateTime Min { get { return _min; } }
public DateTime Max { get { return _max; } }
/// <summary>
/// Uses generator to get the start and end dates of this range.
/// </summary>
/// <param name="middle">The midpoint of this DateTimeRange</param>
/// <param name="generator">Generates the min and max dates from the midpoint and a parameter</param>
public DateTimeRange(DateTime middle, Func<DateTime, int, DateTime> generator, int value)
{
_min = generator(middle, -value);
_max = generator(middle, +value);
}
public bool Of(DateTime dateTime)
{
return _min <= dateTime && dateTime <= _max;
}
}
I feel a little ashamed to post this as the only other answer to a question #jonskeet has answered.

Compare two dates with a range

is it possible to have something that can compare two dates in this format..
example today "Sep 30, 2013" and one week ago "Sep 22, 2013"
if its within this range say "good" if older then say "not good"
how can I make this in C# or vb.net
If difference between dates is smaller than 7 days, it will print "good" otherwise "Not good"
var ok = (firstDate-secondDate).TotalDays < 7? "good": "Not good";
Console.WriteLine(ok);
TotalDays is double so you can check if differnce is in full days, use Days if you want completed days difference as int
Read more about TimeSpan and it's properties.
if(date1 >= Convert.ToDateTime("Sep 22, 2013") && date1 <= Convert.ToDateTime("Sep 30, 2013"))
{
good
}
else
{
bad
}
You can use this generic Range class for checking some comparable value (like DateTime) falls into range:
public class Range<T>
where T : IComparable
{
public Range(T from, T to)
{
if (from.CompareTo(to) > 0)
throw new ArgumentException("From should not be greater than To");
From = from;
To = to;
}
public T From { get; private set; }
public T To { get; private set; }
public bool Contains(T value)
{
return value.CompareTo(From) >= 0 && value.CompareTo(To) <= 0;
}
// other methods like Intersects etc
}
Usage:
var today = DateTime.Today;
var range = new Range<DateTime>(today.AddDays(-7), today);
DateTime date = new DateTime(2013, 9, 25);
if (range.Contains(date))
// say good
thanks to all users who helped me here.. this is the final code that I am using..
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim fileDate As Date = Convert.ToDateTime("Sep 25, 2013")
Dim rightNow As Date = Convert.ToDateTime(Date.Now.ToString("MMM dd, yyyy"))
Dim lastWeek = rightNow.AddDays(-7)
If rightNow >= fileDate And lastWeek <= fileDate Then
Debug.Print("its new")
Else
Debug.Print("too old")
End If
End Sub

Elegantly check if a given date is yesterday

Assuming you have a Unix timestamp, what would be an easy and/or elegant way to check if that timestamp was some time yesterday?
I am mostly looking for solutions in Javascript, PHP or C#, but pseudo code and language agnostic solutions (if any) are welcome as well.
In C# you could use this:
bool isYesterday = DateTime.Today - time.Date == TimeSpan.FromDays(1);
You can use this in C#:
bool isYesterday = (dateToCheck.Date.AddDays(1) == DateTime.Now.Date);
PHP:
$isYesterday = date('Ymd', $timestamp) == date('Ymd', strtotime('yesterday'));
In pseudo code, to compare timestamps:
get current Unix timestamp
transform the retrieved timestamp to a date
subtract 1 day from the date
transform the timestamp to test to a date
compare both dates. If they're equal the tested timestamp was yesterday.
Watch out for timezones if you show the results to a user. For me it's now 13:39 on July 9 2010. A timestamp for 14 hours ago for me is yesterday. But for someone in a different timezone where it's now 15:39, 14 hours ago wasn't yesterday!
Another problem might be systems with a wrong time/date setup. For example if you use JavaScript and the system time of the visitors PC is wrong, the program may come to a wrong conclusion. If it's essential to get a correct answer, retrieve the current time from a known source with a correct time.
An example in Smalltalk using Pharo/Squeak
(Date year: 2014 month: 4 day: 24) = Date yesterday
This accepts an optional DateTimeZone object. If it's not given, it uses the currently set default timezone.
<?php
function isYesterday($timestamp, $timezone = null) {
$t = new DateTime(null, $timezone);
$t->setTimestamp($timestamp);
$t->setTime(0,0);
$yesterday = new DateTime("now", $timezone);
$yesterday->setTime(0,0);
$yesterday = $yesterday->sub(new DateInterval('P1D'));
return $t == $yesterday;
}
Another C# example:
bool isYesterday = DateTime.Now.Date.AddDays(-1) == dateToCheck.Date;
Code:
static class ExtensionMethods
{
private static readonly DateTime UnixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0);;
public static bool IsYesterday(this int unixTime)
{
DateTime convertedTime = UnixStart.AddSeconds(unixTime);
return convertedTime.Date == DateTime.Now.AddDays(-1).Date;
}
public static bool IsYesterday(this DateTime date)
{
return date.Date == DateTime.Now.AddDays(-1).Date;
}
}
Examples:
public class Examples
{
public void Tests()
{
if (1278677571.IsYesterday()) System.Console.WriteLine("Is yesterday");
DateTime aDate = new DateTime(2010, 12, 31);
if (aDate.IsYesterday()) System.Console.WriteLine("Is yesterday");
}
}
In JavaScript, you could write
var someDate = new Date(2010, 6, 9);
Date.yesterday.date == someDate.date // true
Left out needless implementation details, but it's possible. Ok, there ya go :)
(function() {
function date(d) {
var year = d.getFullYear();
var month = d.getMonth();
var day = d.getDate();
return new Date(year, month, day);
}
Object.defineProperty(Date, 'yesterday', {
enumerable: true,
configurable: false,
get: function() {
var today = new Date();
var millisecondsInADay = 86400000;
var yesterday = new Date(today - millisecondsInADay);
return yesterday;
},
set: undefined
});​​​​​​​​
Object.defineProperty(Date.prototype, 'date', {
enumerable: true,
configurable: true,
get: function() {
return date(this).valueOf();
},
set: undefined
});
})();
C#
TimeSpan difference = DateTime.Now.Date - olderDate.Date;
bool isYesterday = difference.TotalDays == 1;
You can give this function a shot:
public bool IsFromYesterday(long unixTime) {
DateTime convertedTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
convertedTime.AddSeconds(unixTime);
DateTime rightNow = DateTime.Now;
DateTime startOfToday = DateTime.Today;
DateTime startOfYesterday = startOfToday - new TimeSpan(1, 0, 0, 0);
if (convertedTime > startOfYesterday && convertedTime < rightNow)
return true;
else
return false;
}

Categories