Suppose i have a DateTime, e. g. 2010.12.27 12:33:58 and i have an interval frames of, suppose, 2 seconds, excluding the last border.
So, i have the following frames:
12:33:58(incl.)-12:34:00(excl.) - let it be interval 1
12:34:00(incl.)-12:34:02(excl.) - let it be interval 2
12:34:02(incl.)-12:34:04(excl.) - let it be interval 3
and so on.
I'm given a random DateTime value and i have to correlate that value according the above rules.
E. g. the value "12:33:58" falls into interval 1, "12:33:59" falls into interval 1, "12:34:00" falls into interval 2 and so on.
In code it should look like the following:
var dt = DateTime.Now;
DateTime intervalStart = apply_the_algorythm(dt);
It seems to be some simple arithmetic action(s) with float or something, any decisions are welcome!
If the interval is only second resolution and always divided 86400, then take the number of seconds that have passed today, divide it by the interval, round it to an integer value, multiply it, and add it back to today. Something like dateinquestion.Subtract(dateinquestion.Date).TotalSeconds, ((int)seconds/interval)*interval, dateinquestion.Date.AddSeconds(...)
If you want the range of all your intervals to span several days, possibly a long time, you might want to express your DateTime values in UNIX-seconds (the number of seconds since 1970-01-01). Then you just find out when your very first interval started, calculate how many seconds passed since then, and divide by two:
int secondsSinceFirstInterval = <currDate in UNIX time>
- <start of first interval in UNIX time>;
int intervalIndex = secondsSinceFirstInterval / 2;
Otherwise you're better off just counting from midnight.
Use TimeSpan.TotalSeconds and divide the result by the size of the interval.
const long intervalSize = 2;
DateTime start = new DateTime(2010, 12, 27, 12, 33, 58);
TimeSpan timeSpan = DateTime.Now - start;
long intervalInSeconds = (long)timeSpan.TotalSeconds;
long intervalNumber = 1 + intervalInSeconds / intervalSize;
DateTime start = new DateTime(2010, 12, 31, 12, 0, 0);
TimeSpan frameLength = new TimeSpan(0, 0, 3);
DateTime testTime = new DateTime(2010, 12, 31, 12, 0, 4);
int frameIndex = 0;
while (testTime >= start)
{
frameIndex++;
start = start.Add(frameLength);
}
Console.WriteLine(frameIndex);
dates = new List<DateTime>
{
DateTime.Now.AddHours(-1),
DateTime.Now.AddHours(-2),
DateTime.Now.AddHours(-3)
};
dates.Sort((x, y) => DateTime.Compare(x.Date, y.Date));
DateTime dateToCheck = DateTime.Now.AddMinutes(-120);
int place = apply_the_algorythm(dateToCheck);
Console.WriteLine(dateToCheck.ToString() + " is in interval :" +(place+1).ToString());
private int apply_the_algorythm(DateTime date)
{
if (dates.Count == 0)
return -1;
for (int i = 0; i < dates.Count; i++)
{
// check if the given date does not fall into any range.
if (date < dates[0] || date > dates[dates.Count - 1])
{
return -1;
}
else
{
if (date >= dates[i]
&& date < dates[i + 1])
return i;
}
}
return dates.Count-1;
}
Related
I'm trying to check if a DateTime is greater than another DateTime in a method, but when I try to pass it through the paramaters it says that one of the DateTime is 01/01/0001 even though I didn't pass it through as such.
Method:
int monthsCount2(DateTime date, DateTime birthday, int yOld)
{
int count = 0;
if (birthday.Date >= date.Date)
{
count++;
if (!(yOld == 0))
count += (yOld - 1);
}
else
count += yOld;
return count;
}
Using the method:
Console.WriteLine("You have lived through {0} christmases.",
monthsCount2(christmas, birthDay, (int)yearsOld));
christmas variable:
DateTime christmas = new DateTime(25 / 12 / 2017);
birthDay variable:
try
{
Console.WriteLine("Please enter your Birthdate. (dd/MM/yyyy)");
string input = Console.ReadLine();
birthDay = DateTime.Parse(input);
if (birthDay > DateTime.Now)
throw new FormatException();
}
yearsOld variable:
TimeSpan secondsTimeSpan = DateTime.Now - birthDay;
double secondsOld = Math.Round(secondsTimeSpan.TotalSeconds);
double minutesOld = Math.Round(secondsOld / 60);
double hoursOld = Math.Round(minutesOld / 60);
double daysOld = Math.Round(hoursOld / 24);
double weeksOld = Math.Round(daysOld / 7);
double monthsOld = Math.Round(weeksOld / 4.34524);
double yearsOld = Math.Round(monthsOld / 12, 1);
Input - Console:
Console - Imgur
Locals Debug:
Locals - Imgur
All Code:
Code - Github
The correct syntax to initialize a datetime instance is this:
var christmas = new DateTime(2017, 12, 25);
The constructor is documented here.
And the reason why your approach did not work:
You are dividing 25 by 12, then dividing the result of that by 2017. as an integer, this will be zero, as a date this will be DateTime.MinValue which is 01/01/0001.
So why does the compiler not reject your attempted date literal? Because there is a constructor which takes an Int64 that fits the division expression. It has altogether different semantics though, it represents the
number of 100-nanosecond intervals that have elapsed since January 1, 0001 at 00:00:00.000 in the Gregorian calendar
This is incorrect syntax (or at very least not what you think it is)
DateTime christmas = new DateTime(25 / 12 / 2017);
The numeric values are integers and '/' is divide.
Instead you want to do something like this:
DateTime christmas = new DateTime(2017, 12, 25);
or
DateTime christmas = new DateTime.Parse("12/25/2017");
The format on that last one is culturally dependent.
In a scenario where you would need to calculate the next 'Billing date' if the DAY (2nd, 25th, etc) is known, how can you calculate the number of days left until the next bill payment?
Explanation:
Tom's bill gets generated on the 4th of every month
What's the best way/logic to calculate the days left until the next bill? For example, if today is the 28th of this month, the result would be 6 days left
What we know:
Bill Generation Date is known
Today's Date is known
What I've done so far:
int billingDay = 4; //The day the bill gets generated every month
DateTime today = DateTime.Today; //Today's date
How would I continue this to calculate the next billing date?
P.S: Sorry if this sounds lame, I just couldn't wrap my head around it :)
I think this works:
private int GetNumDaysToNextBillingDate(int billingDayOfMonth)
{
DateTime today = DateTime.Today;
if (today.Day <= billingDayOfMonth)
{
return (new DateTime(today.Year, today.Month, billingDayOfMonth) - today).Days;
}
else
{
var oneMonthFromToday = today.AddMonths(1);
var billingDateNextMonth =
new DateTime(oneMonthFromToday.Year,
oneMonthFromToday.Month, billingDayOfMonth);
return (billingDateNextMonth - today).Days;
}
}
How about:
int billingDay = 4;
DateTime today = DateTime.UtcNow;
DateTime billing = today.Day >= billingDay
? new DateTime(today.AddMonths(1).Year, today.AddMonths(1).Month, billingDay)
: new DateTime(today.Year, today.Month, billingDay);
TimeSpan left = billing - today;
This uses a loop but is less prone to error as it takes into account month and year changes:
int DaysUntilBilling(int billingDay, DateTime referenceDate)
{
int count = 0;
while (referenceDate.AddDays(count).Day != billingDay)
{
count++;
};
return count;
}
You of course don't need to pass a DateTime in as an argument if you are always using today's date, but this helps to test that that for different inputs, you get the desired output:
int billingDay = 4;
DaysUntilBilling(billingDay, DateTime.Now); //26 (today is 9th Aug 2016)
DaysUntilBilling(billingDay, new DateTime(2016, 09, 03); //1
DaysUntilBilling(billingDay, new DateTime(2016, 09, 04); //0
DaysUntilBilling(billingDay, new DateTime(2016, 08, 05); //30
DaysUntilBilling(billingDay, new DateTime(2016, 12, 19); //16
This link might help you :
https://msdn.microsoft.com/en-us/library/system.datetime.daysinmonth(v=vs.110).aspx
What you can do is something like this:
int daysUntilBill = 0;
int billingDay = 4;
DateTime today = DateTime.Today;
if (billingDay > today.Day) {
daysUntilBill = billingDay - today.Day;
} else {
int daysLeftInMonth = DateTime.DaysInMonth(today.Year, today.Month) - today.Day;
daysUntilBill = billingDay + daysLeftInMonth;
}
or slightly more concise
int daysUntilBill = (billingDay >= today.Day)
? billingDay - today.Day
: billingDay + DateTime.DaysInMonth(today.Year, today.Month) - today.Day;
This properly handles the year ending too, since it doesn't try to wrap around.
First you need to determine if the current date is on or before the billing day and if it is just subtract the current day of the month. Otherwise you have to determine the next billing date in the following month.
public int DaysToNextBill(int billingDay)
{
var today = DateTime.Today;
if(today.Day <= billingDay)
return billingDay - today.Day;
var nextMonth = today.AddMonth(1);
var nextBillingDate = new DateTime(nextMonth.Year, nextMonth.Month, billingDay)
return (nextBillingDate - today).Days;
}
The only thing left to deal with is if billingDay is greater than the number of days in the current or following month.
I made a little parking application in C#. There are some different pricings depending on vehicle type and time zone. Day can be divided into time zones (for example morning, day, evening and night). Now if customer stops parking I want to calculate in which time zones customer has parked and how long.
For example morning time zone starts at 6:00 and ends 12:00, day time zone starts at 12:00 and ends 16:00, evening time zone starts at 16:00 and ends at 23:00 and night time zone starts at 23:00 and ends at 6:00. Customer started parking his car at 00:30 and ends parking at 6:32. Currently I have 4 variables for that: parking start time, parking end time and timezone starting time and timezone ending time.
Second example would be like customer parks 24H, then the parking time has all time zones covered.
How is the simplest way to calculate how many hours and minutes customer parked his car in different time zones?
Regards,
evilone
EDIT:
Got this answer from MSDN and post it here so others can learn from it too.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DateTime start = new DateTime(2011, 7, 25, 0, 30, 0);
DateTime end = new DateTime(2011, 7, 26, 6, 32, 0);
List<DateTime> listTimeZones = CalculateTotalTime(start, end);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < listTimeZones.Count; i++)
{
sb.AppendLine(String.Format("{0}. {1}: from {2} to {3}",
i + 1,
GetZoneInWords(listTimeZones[i].Hour),
String.Format("{0:dd.MM.yyyy hh:mm}", listTimeZones[i]),
(i + 1) < listTimeZones.Count
? String.Format("{0:dd.MM.yyyy hh:mm}", listTimeZones[i + 1])
: "Parking ended"));
}
MessageBox.Show(sb.ToString());
}
private List<DateTime> CalculateTotalTime(DateTime start, DateTime end)
{
DateTime temp = start;
int hour = start.Hour;
int minute = start.Minute;
int morning = 6;
int day = 12;
int evening = 17;
int night = 23;
List<DateTime> timeZones = new List<DateTime>();
do
{
temp = temp.AddHours(1);
if (temp.Hour == morning || temp.Hour == day ||
temp.Hour == evening || temp.Hour == night)
{
timeZones.Add(temp);
}
} while (temp < end);
return timeZones;
}
private string GetZoneInWords(int time)
{
string timeOfDay = "";
if (time.Equals(6))
timeOfDay = "Morning";
else if (time.Equals(12))
timeOfDay = "Day";
else if (time.Equals(17))
timeOfDay = "Evening";
else if (time.Equals(23))
timeOfDay = "Night";
return timeOfDay + " parking";
}
}
Iterate through all the "time zones" and for each, work out the overlap between that and the customer's parking. For example, as pseudo-code:
private static TimeSpan FindOverlap(ParkingTime parkingTime, TimeZone timeZone)
{
// Handle wraparound zones like 23-6. Note that this doesn't attempt
// to handle *parking* which starts at 11.30pm etc.
if (timeZone.Start > timeZone.End)
{
return FindOverlap(parkingTime,
new TimeZone(timeZone.Start.Date, timeZone.End)
+ FindOverlap(parkingTime,
new TimeZone(timeZone.End, timeZone.Start.Date.AddDays(1));
}
DateTime overlapStart = Max(parkingTime.Start, timeZone.Start);
DateTime overlapEnd = Min(parkingTime.End, timeZone.End);
TimeSpan overlap = overlapEnd - overlapStart;
// If the customer arrived after the end or left before the start,
// the overlap will be negative at this point.
return overlap < TimeSpan.Zero ? TimeSpan.Zero : overlap;
}
private static DateTime Min(DateTime x, DateTime y)
{
return x < y ? x : y;
}
private static DateTime Max(DateTime x, DateTime y)
{
return x > y ? x : y;
}
By the way, I would strongly encourage you to rename your "time zone" concept, given that it already has a well-known (if not well-understood :) meaning.
Perhaps you should call it ParkingInterval? Or ParkingPriceInterval if the difference is really in terms of cost?
I need to produce a list of date ranges, so that the output will eventually be:
0 – 28/02/2009 to 31/02/2010
1 – 31/03/2009 to 31/03/2010
2 – 30/04/2009 to 30/04/2010
3 – 31/05/2009 to 31/05/2010
4 – 30/06/2009 to 30/06/2010
5 – 31/07/2009 to 31/07/2010
6 – 31/08/2009 to 31/08/2010
7 – 30/09/2009 to 30/09/2010
8 – 31/10/2009 to 31/10/2010
9 – 30/11/2009 to 30/11/2010
10 – 31/12/2009 to 31/12/2010
11 – 31/01/2010 to 31/01/2011
12 – 28/02/2010 to 28/02/2011
So I've created a for loop to start with the latestDate - 1 year as the first element's end date, and a start date of the end date - 1 year, and then to incremement the loop's index by 1 month each iteration, as follows:
DateTime latestDate = new DateTime(2011, 2, 28);
int noOfYears = 1; // could vary
int shift = 1; // could vary
Dictionary<DateTime, DateTime> dateRanges = new Dictionary<DateTime, DateTime>();
for (var currentDate = latestDate.AddYears(noOfYears *= -1);
currentDate <= latestDate; currentDate.AddMonths(shift))
{
dateRanges.Add(currentDate.AddYears(noOfYears *= -1), currentDate);
}
I thought this would work smashingly but for some reason that I don't understand currentDate.AddYears(noOfYears *= -1) doesn't seem to be working, because the first entry in the dictionary is:
28/02/2011 , 28/02/2010 // the first date here should be minus 2 years!?
Where I would have expected
28/02/2009 , 28/02/2010 // the first in the list above
When the loop iterates for the second time the second entry to the dictionary is:
28/02/2009 , 28/02/2010 // this should be first in the dictionary!
Is there something obviously wrong with my logic that I'm not seeing?
You're constantly multiplying the noOfYears variable by -1, so it keeps switching between -1 and 1. Try using noOfYears * -1 instead (without the equals-sign).
currentDate.AddYears(noOfYears *= -1)
will flip the value of noOfYears back and forth from 1 to -1, to 1, to -1, ...
I'm not sure why you need to do this.
Also you are not changing the value of currentDate. Try this:
// note the new start date
DateTime latestDate = new DateTime(2011, 3, 1);
// could vary
int noOfYears = 1;
// could vary
int shift = 1;
var dateRanges = new Dictionary<DateTime, DateTime>();
for (var currentDate = latestDate.AddYears(noOfYears * -1);
currentDate <= latestDate; currentDate = currentDate.AddMonths(shift))
{
dateRanges.Add(currentDate.AddYears(noOfYears *= -1).AddDays(-1),
currentDate.AddDays(-1));
}
I am trying to calculate the difference between two dates. This is what I'm currently using:
int currentyear = DateTime.Now.Year;
DateTime now = DateTime.Now;
DateTime then = new DateTime(currentyear, 12, 26);
TimeSpan diff = now - then;
int days = diff.Days;
label1.Text = days.ToString() + " Days Until Christmas";
All works fine except it is a day off. I am assuming this is because it does not count anything less than 24 hours a complete day. Is there a way to get it to do so? Thank you.
int days = (int)Math.Ceiling(diff.TotalDays);
The question is rather philosophic; if Christmas was tomorrow, would you consider it to be 1 day left, or 0 days left. If you put the day of tomorrow into your calculation, the answer will be 0.
Your problem goes away if you replace your:
DateTime.Now
with:
DateTime.Today
as your difference calculation will then be working in whole days.
I normally use the following code to get the output as intended by the unit in which the output is required:
DateTime[] dd = new DateTime[] { new DateTime(2014, 01, 10, 10, 15, 01),new DateTime(2014, 01, 10, 10, 10, 10) };
int x = Convert.ToInt32((dd[0] - dd[1]).TotalMinutes);
String unit = "days";
if (x / 60 == 0)
{
unit = "minutes";
}
else if (x / 60 / 24 == 0)
{
unit = "hours";
x = x / 60;
}
else
{
x = x / (60 * 24);
}
Console.WriteLine(x + " " + unit);