Convert week and year to milliseconds - c#

I need to convert, as the title says, weeks and year to milliseconds since 1970. What is the best way to do this in .Net?
I only have information of the week and year that some event occurred. The week stars on Monday. I think DateTime is not the answer since it can't handle the week of the year.
What I need is something like a method double getMili(int week, int year).
Thanks anyway

You can put it like that:
// Let's convert 15th Monday in 2014
int MondaysNumber = 15;
DateTime source = new DateTime(2014, 1, 1);
int delta = 7 + DayOfWeek.Monday - source.DayOfWeek;
if (delta >= 7)
delta -= 7;
source = source.AddDays((MondaysNumber - 1) * 7 + delta);
// Finally, convert it into milliseconds
Double result = (source - new DateTime(1970, 1, 1)).TotalMilliseconds;

Related

Get next given day after a month in c#

How can I get the next particular day after a month in c#,
for example if today is Monday I need to get the first Monday after 1 month from now, but in more generic way, for example if today is 17/11/2021 which is Wednesday I need to get the first Wednesday after a month from now.
I am using this function but it will return for next week and not next month:
public static DateTime GetNextWeekday(DateTime start, DayOfWeek day)
{
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysToAdd = ((int)day - (int)start.DayOfWeek + 7) % 7;
return start.AddDays(daysToAdd);
}
Typical month has 30 or 31 days, however, the next same day of week will be after either 28 (4 * 7) or 35 (5 * 7) days. We need a compromise. Let for February add 28 days and for all the other months add 35 days:
public static DateTime GetSameDayAfterMonth(DateTime start) =>
start.AddDays((start.AddMonths(1) - start).TotalDays < 30 ? 28 : 35);
Sure, you can elaborate other rules: say, when after adding 28 days we are still in the same month (1 May + 28 days == 29 May) we should add 35:
public static DateTime GetSameDayAfterMonth(DateTime start) =>
start.AddDays(start.Month == start.AddDays(28).Month ? 35 : 28);
Add a month, instead of a week to the start date:
public static DateTime GetSameDayAfterMonth(DateTime start)
{
var compare = start.AddMonths(1);
// The % 7 ensures we end up with a value in the range [0, 6]
int daysToAdd = ((int)start.DayOfWeek - (int)compare.DayOfWeek) % 7;
return compare.AddDays(daysToAdd);
}
Example:
var dayInNextMonth = GetSameDayAfterMonth(DateTime.Parse("2021-11-17")); // 2021-12-15
var weekday = dayInNextMonth.DayOfWeek; // Wednesday

Return the correct number of weeks for the Gregorian Calendar

I have a problem with the calendar that I use to get me a smaller number of weeks for certain months
For example, this happens to me at Sept 2019, where my number is 5 or in July 2018, which is also 5.
How can I fix this?
this is my current code:
private DateTime _calendarDate;
int numWeeks = NumberOfWeeks(_calendarDate.Year, _calendarDate.Month);
private int NumberOfWeeks(int year, int month)
{
return NumberOfWeeks(new DateTime(year, month, DateTime.DaysInMonth(year, month)));
}
private int NumberOfWeeks(DateTime date)
{
var beginningOfMonth = new DateTime(date.Year, date.Month, 1);
while (date.Date.AddDays(1).DayOfWeek != CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
date = date.AddDays(1);
return (int)Math.Truncate(date.Subtract(beginningOfMonth).TotalDays / 7f) + 1;
}
additional information on CultureInfo
The problem is that it always comes back to me one week less, so my calendar doesn't display it properly and then I get the error,
Here's an example for April 2018 where you give me 5 weeks, and then another one is missing and that's why I'm getting the error
can anyone guess how i could solve this problem?
When you can use System.Globalization.Calendar you can get the count of weeks in a month by using GetWeekOfYear for the first and the last day of the month and then calculate the difference (and add 1 to include the first week).
This would change your NumberOfWeeks() to the following:
private int NumberOfWeeks(DateTime date)
{
Calendar calendar = CultureInfo.CurrentCulture.Calendar;
var firstOfMonth = new DateTime(date.Year, date.Month, 1);
var week1 = calendar.GetWeekOfYear(firstOfMonth, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
var week2 = calendar.GetWeekOfYear(date, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
int numberOfWeeks = (week2 - week1) + 1;
return numberOfWeeks;
}
For your example (April 2018) this will give you 6 as a result and for May 2018 it will give you 5.
MSDN GetWeekOfYear
Here is a bit more mathematical solution:
int myYear = 2019, myMonth = 12; // the example for December 2019
var firstMonthDay = new DateTime(myYear, myMonth, 1);
int delta = firstMonthDay.DayOfWeek - System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
if (delta < 0)
delta += 7;
int daysInMonth = DateTime.DaysInMonth(myYear, myMonth);
int weekLinesNumber = (int)Math.Ceiling((daysInMonth + delta) / 7F); // the result
We count the delta (could be from 0 to 6), this is the number of days from the first day of the week to the first next month day. Then we count the resulting number of the weeks using Math.Ceiling function.
In short, we add to the month some delta days at the beginning in order to get new Extra Month block starting from the First Day of a Week (according to the culture). And then we count the total number of the occupied week lines. No need to add +1 when we use Math.Ceiling function.

How to convert year, month and day to ticks without using DateTime

long ticks = new DateTime(2012, 1, 31).ToLocalTime().Ticks; // 634635684000000000
But how to do this without DateTime constructor ?
edit
What I actually want is to keep only the years, months and days from the ticks.
long ALL_Ticks = DateTime.Now.Ticks; // 634636033446495283
long Only_YearMonthDay = 634635684000000000; // how to do this ?
I want to use this in a linq-sql query using Linq.Translations.
If you only want the ticks for the date portion of the current datetime you could use:
long Only_YearMonthDay = DateTime.Now.Date.Ticks; //634635648000000000
//DateTime.Now.Date.Ticks + DateTime.Now.TimeOfDay.Ticks == DateTime.Now.Ticks
You could find out how many days are in the calculation and then multiply by 864,000,000,000 (which is how many ticks are in a day). Is that what you are looking for? Bit of documentation here : http://msdn.microsoft.com/en-us/library/system.timespan.ticksperday.aspx.
Happy coding,
Cheers,
Chris.
OK - didn't think this through properly! Ticks represent the amount of 100 nanosecond intervals since 12:00:00 midnight, January 1, 0001. You would need to calculate how many days have passed since that date and then multiply it by the ticks per day value!
If I understand you right, you are not worried about the ticks up to a particular time of the day?! So, it would be something along the lines of :
var ticksToDate = (DateTime.UtcNow - DateTime.MinValue).Days * 864000000000;
Does that answer your question??
That is going to be rather difficult unless you have some other way of getting the current date and time. According to MSDN:
A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond.
The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001, which represents DateTime.MinValue. It does not include the number of ticks that are attributable to leap seconds.
Now, if you know the current date and time, you can calculate how many days have passed since January 1, 0001 and use that to calculate the number of ticks.
I understand you dont want the hour parts of the date. If you use Date, then you only get the day (for example: 01/01/2012 00:00:00)
long ticks = new DateTime(2012, 1, 31).Date.Ticks;
And with any DateTime object already created is the same of course.
long ticks = dateObject.Date.Ticks;
You already have the answer there in your post:
long ALL_Ticks = DateTime.Now.Ticks;
// that's the ticks (from DateTime.MinValue) until 'now' (this very moment)
long ticks = new DateTime(2012, 1, 31).ToLocalTime().Ticks;
// or
long ticks = DateTime.Now.Date.Ticks;
// that's the ticks until the beginning of today
long yearmonthticks = new DateTime(2012, 1, 1).ToLocalTime().Ticks;
// that's the ticks until the beginning of the month
// etc..., the rest is simple subtractions
Since your question doesn't specify any reason not to use the DateTime constructor, this is the best solution for what seems like your problem.
I had a use case where I couldn't use DateTime but needed Years/Months from Ticks.
I used the source behind DateTime to figure out how. To go the other way you can look at the constructor, one of which calls the following code.
private static long DateToTicks(int year, int month, int day) {
if (year >= 1 && year <= 9999 && month >= 1 && month <= 12) {
int[] days = IsLeapYear(year)? DaysToMonth366: DaysToMonth365;
if (day >= 1 && day <= days[month] - days[month - 1]) {
int y = year - 1;
int n = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
return n * TicksPerDay;
}
}
throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
}
This can be found in link below, of course you will need to re-write to suit your needs and look up the constants and IsLeapYear function too.
https://referencesource.microsoft.com/#mscorlib/system/datetime.cs,602

TimeSpan for different years subtracted from a bigger TimeSpan

The language I am using is C#.
I have the folowing dillema.
DateTime A, DateTime B. If A < B then I have to calculate the number of days per year in that timespan and multiply it by a coeficient that corresponds to that year.
My problem is the fact that it can span multiple years.
For example:
Nr of Days in TimeSpan for 2009 * coef for 2009 + Nr of Days in TimeSpan for 2010 * coef for 2010 + etc
You can't do this with a simple TimeSpan, basically. It doesn't know anything about when the span covers - it's just a number of ticks, really.
It sounds to me like there are two cases you need to consider:
A and B are in the same year. This is easy - just subtract one from the other and get the number of days from that
A and B are in different years. There are now either two or three cases:
The number of days after A in A's year. You can work this out by constructing January 1st in the following year, then subtracting A
The number of days in each year completely between A and B (so if A is in 2008 and B is in 2011, this would be 2009 and 2010)
The number of days in B's year. You can work this out by constructing December 31st in the previous year, then subtracting B. (Or possibly January 1st in B's year, depending on whether you want to count the day B is on or not.)
You can use DateTime.IsLeapYear to determine whether any particular year has 365 or 366 days in it. (I assume you're only using a Gregorian calendar, btw. All of this changes if not!)
Here is a little snippet of code that might help
var start = new DateTime(2009, 10, 12);
var end = new DateTime(2014, 12, 25);
var s = from j in Enumerable.Range(start.Year, end.Year + 1 - start.Year)
let _start = start.Year == j ? start : new DateTime(j, 1, 1)
let _end = end.Year == j ? end : new DateTime(j, 12, 31)
select new {
year = j,
days = Convert.ToInt32((_end - _start).TotalDays) + 1
};
If I understood your problem correctly, solving it using Inclusion Exclusion principle would be the best.
Say, if your start date is somewhere in 2008 and the end date is in 2010:
NDAYS(start, end) * coeff_2008
- NDAYS(2009, end) * coeff_2008 + NDAYS(2009, end) * coeff_2009
- NDAYS(2010, end) * coeff_2009 + NDAYS(2010, end) * coeff_2010
Where Ndays computes the number of dates in the interval (TotalDays plus one day).
There is no need to handle leap years specially or compute december 31st.
The details you can work out in a for-loop going over jan first of each year in the span.

Subtracting TimeSpan from date

I want to subtract a time-span from a date-time object using a 30-day month and ignoring leap years etc.
Date is 1983/5/1 13:0:0 (y/m/d-h:m:s)
Time span is 2/4/28-2:51:0 (y/m/d-h:m:s)
I can use DateTime and TimeSpan objects to do this, after converting years and months of the time-span to days (assuming a 30 day month and a ~364 day year).
new DateTime(1981,5,1,13,0,0).Subtract(new TimeSpan(878,13,51,0));
With this i get the result:
{12/4/1978 11:09:00 PM}
Above answer obviously doesn't ignore the factors i want ignored and gives me an accurate answer. But in this case that's not what i want so i wrote the below code.
public static CustomDateTime operator -(CustomDateTime DT1,CustomDateTime DT2)
{
CustomDateTime retVal = new CustomDateTime();
try
{
const int daysPerYear = 364.25;
const int monthsPerYear = 12;
const int daysPerMonth = 30;
const int hoursPerDay = 24;
const int minutesPerHour = 60;
retVal.Minute = DT1.Minute - DT2.Minute;
if (retVal.Minute < 0)
{
retVal.Minute += minutesPerHour;
DT1.Hour -= 1;
}
retVal.Hour = DT1.Hour - DT2.Hour;
if (retVal.Hour < 0)
{
retVal.Hour += hoursPerDay;
DT1.Day -= 1;
}
retVal.Day = DT1.Day - DT2.Day;
if (retVal.Day < 0)
{
retVal.Day += daysPerMonth;
DT1.Month -= 1;
}
retVal.Month = DT1.Month - DT2.Month;
if (retVal.Month < 0)
{
retVal.Month += monthsPerYear;
DT1.Year -= 1;
}
retVal.Year = DT1.Year - DT2.Year;
}
catch (Exception ex) { }
return retVal;
}
Then i get:
1981/0/3-10:9:0
This is pretty close to what i'm after except i shouldn't get 0 for month and year should be 1980. Any kind of help is appreciated.
Just to make things clear again; in this context I have to use a 30-day month and ignore leap-years, different numbers of months, etc. Its a weird thing to do, i know. So I'm pretty much after a 'wrong answer' as opposed to the exact answer given by the managed classes.
If you're estimating a month at 30 days, of course your math will be off. When you subtract 878 days from 5/1/1981, .Net is giving you the exact difference, not an estimate, and this difference accounts for leap years, if there are any. The error is not in the Subtract(...) method - it is in your own "manual" calculation.
DateTime dt = new DateTime(1981, 5, 1, 13, 0, 0);
TimeSpan t = new TimeSpan(878, 13, 51, 0);
dt.Ticks
624931668000000000
t.Ticks
759090600000000
dt.Ticks - t.Ticks
624172577400000000
new DateTime(dt2)
{12/4/1978 11:09:00 PM}
Date: {12/4/1978 12:00:00 AM}
Day: 4
DayOfWeek: Monday
DayOfYear: 338
Hour: 23
Kind: Unspecified
Millisecond: 0
Minute: 9
Month: 12
Second: 0
Ticks: 624172577400000000
TimeOfDay: {23:09:00}
Year: 1978
These are the total ticks since the epoch. Do this math, then convert back into a datetime.
Also: correct your math. 878 days is 2 years and 148 days. 5/1/1981 is the 121st day of the year, so subtract 120 to get Jan 1, 1979. This leaves 28 days. Start counting backwards from the end of 1978, and you get very close to the .Net answer. Your own answer isn't anywhere close.
EDIT based on feedback
// zh-Hans is a chinese culture
CultureInfo ci = CultureInfo.GetCultureInfo("zh-Hans");
DateTime dt = new DateTime(1981, 5, 1, 13, 0, 0, ci.Calendar);
TimeSpan t = new TimeSpan(878, 13, 51, 0);
Please note that you are still subtracting 878 days. The length of a month would be irrelevant in that case based on the Julian calendar. You will probably need to find the correct culture code for your particular calendar, then try this. However, with this calendar, I still arrive at the same answer above.
Beyond doing this, I am unsure how else to do the math. If you can provide a link to how you are doing it by hand, I can help code it for you.
EDIT 2
I understand now. Try this:
DateTime dt = new DateTime(1981, 5, 1, 13, 0, 0, ci.Calendar);
int years = 878 / 365;
int remainingDays = 878 % 365;
int months = remainingDays / 30;
remainingDays = remainingDays % 30;
TimeSpan t = new TimeSpan(years * 365 + months * 30 + remainingDays);
DateTime newdate = dt.Subtract(t);
You cannot assume a 30-day month. You are specifying that you want to subtract 878 days. The managed classes (I'm assuming you mean managed when you say native) are designed to factor in leap-years, different numbers of months, etc.
Using the managed classes will not give you a 0 for a month.

Categories