Task.Duration Property in ms project - c#

How I have to convert Task.Duration that get valid result?
I find explanations about this property in MSDN:
Gets or sets the duration (in minutes) of a task.
But it doesn't work correct.
If I divided result by 60 (minutes in hour) and 24(hours in day) I get incorrect result.
But if I divided by 20 and 24 all it's ok. And I don't understand why.
I use C# on .Net 3.5 and Office Primary Interop Assemblies ( Microsoft.Office.Interop.MSProject for office 2010).
I use that code :
void SetProperties(MSProject.Task o, string version)
{
Wbs = o.WBS.ToString();
Name = o.Name.ToString();
StartDate = (System.DateTime) o.Start;
FinishDate = (System.DateTime)o.Finish;
Iteration = version;
duration = (Convert.ToInt16(o.Duration)/10/24).ToString();//after result //divided by 2 I get correct result. Why?
}
thanks

The reason that it doesn't work like you expect is because in a day you do not have 24 hours of working time. The Duration of a task is the amount of working time between the start and finish, not the absolute number of hours.
Since the default number of working hours in a day is 8, you divide the total minutes by 480 (60 min * 8 hours) to get the number of days. Your calculation of 20 * 24 just so happens to also equal 480, so you stumbled upon the correct number.
Of course, do not expect that Start + Duration (in days) is going to equal your Finish date. That's because you also have to factor in non-working days, like weekends. So you can have a 3 day task that starts on Friday, and it will not finish until the end of the day on Tuesday (5 calendar days).

Related

How to Convert DateTime.Now in 0 to 1 decimal format in c#

I would like to convert the current time to a decimal representing a fraction of the day. For example, if the day starts at 0, then 12:00 PM should be 0.5.
I need to send that value to an API, and it needs to be in that format. i.e.
"LAST_PRINT_TIME":0.22020833"
Depending on the precision requirements of your result, this may help you:
DateTime now = DateTime.Now;
double dayFraction = (now.Hour + now.Minute / 60d) / 24d;
now.Minute / 60d calculates the fraction of the current hour (so if the time is XX:15 PM this will give 0.25). This is then added to the current hour. This value is then divided by 24 to obtain the final result.
For example, 3:45 PM would go as follows:
(15 + 45 / 60) / 24) => (15 + 0.75) / 24 => 15.75 / 24 => 0.65625
So 3:45 PM, which is 15.75 hours into the day, would be 0.65625 (or 65.625%) of the day.
Or, as #madreflection mentioned in a comment, you could use .ToOADate() as well. In this case, you could do something like:
DateTime now = DateTime.Now;
double dayFraction = now.ToOADate() - now.Date.ToOADate();
This is one of those problems that seems deceptively simple, but the solution is actually much more complex than you would think.
The complexities arise from the nature of local time, whose rules are defined by time zones. Many time zones have transitions that occur either regularly (such as for daylight saving time), or irregularly (such as for changes in standard time).
As such, one needs to consider:
Could the day be shorter or longer than 24 hours?
For example, in most of the US the start of DST is at 2:00 AM, and on that day there are 23 hours in the day because the hour from 2:00 to 2:59 is skipped. At the end of DST, also at 2:00 AM in the US, the hour from 1:00 through 1:59 is repeated, creating 25 hours in that day.
Could the day start or stop at a time other than midnight?
For example, in most of Chile in 2019, the start of DST made the date 2019-09-08 start at 01:00 instead of 00:00.
Learn more in Falsehoods programmers believe about time.
Consider using the following approach to overcome these real-world considerations.
First, define some helper functions to do most of the work. They are not specific to a particular point in time or a particular time zone.
static double GetFractionOfDay(DateTimeOffset dto, TimeZoneInfo tz)
{
// Get the start of the day, and the start of the next day
DateTimeOffset startOfDay = GetStartOfDay(dto, tz);
DateTimeOffset startOfNextDay = GetStartOfDay(startOfDay.AddDays(1), tz);
// Calculate the length of the day. It might not be 24 hours!
TimeSpan lengthOfDay = startOfNextDay - startOfDay;
// Now calculate the position within the day, and the fraction to return
TimeSpan durationSinceStartOfDay = dto - startOfDay;
return durationSinceStartOfDay / lengthOfDay;
}
static DateTimeOffset GetStartOfDay(DateTimeOffset dto, TimeZoneInfo tz)
{
// Make sure we're in the correct time zone
dto = TimeZoneInfo.ConvertTime(dto, tz);
// Start by assuming a local midnight exists
DateTime dt = dto.Date;
// Handle days without a local midnight (these do exist in several time zones)
if (tz.IsInvalidTime(dt))
{
// Advance by the transition gap. This is usually 1 hour, but best not to hard-code that.
TimeSpan[] offsets = { tz.GetUtcOffset(dt.AddDays(-1)), tz.GetUtcOffset(dt.AddDays(1)) };
TimeSpan gap = offsets[1] - offsets[0];
return new DateTimeOffset(dt.Add(gap), offsets[1]);
}
// Handle days with more than one midnight (it's possible, even if unlikely)
if (tz.IsAmbiguousTime(dt))
{
// There's more than one. Prefer the first one, since we want the beginning of the day.
TimeSpan[] offsets = tz.GetAmbiguousTimeOffsets(dt);
TimeSpan offset = offsets[0] > offsets[1] ? offsets[0] : offsets[1];
return new DateTimeOffset(dt, offset);
}
// Clean case, just one local midnight and it does exist
return new DateTimeOffset(dt, tz.GetUtcOffset(dt));
}
With those defined, you can now get an answer to your question with regard to "now" in the local time zone.
double dayFraction = GetFractionOfDay(DateTimeOffset.Now, TimeZoneInfo.Local);
However - Though this is the correct answer of "what fraction of the day is it", keep in mind it may be more important to align with what the receiving API expects, even if not exactly correct. In other words, if 12:00 should always be 0.5, even when it's not exactly at the midpoint of the day, then use elmer007's approach.

Calculate hour difference between given date and current date in C#

I want to check to see how many hours difference there are between a given date and the current date. I'm looking for a date that's less then 24 hours away!
I thought this would work but it's giving me a true statement when the EventDateTime is Sunday which is greater then 24 hours out!
bool lessThen24Hours = (spaceEvent.EventDateTime - DateTime.Now).Hours < 24 ? true : false;
you want the TotalHours property rather than Hours:
bool lessThen24Hours = (spaceEvent.EventDateTime - DateTime.Now).TotalHours < 24;
Try (spaceEvent.EventDateTime - DateTime.Now).TotalHours.
It gives you all the hours distance between two dates
Use .TotalHours
(spaceEvent.EventDateTime - DateTime.Now).TotalHours < 24
put that inside Math.Abs() if you want the proximity of 24 hour regardless which time is first
Use DateTimeOffset instead of DateTime so that time zones don't mess up your math.

Finding uptime of a program but showing it in MINUTES

So I run some type of game, and I want to add a command !uptime that displays how long server has been running for since the last open or whatever
This code (from microsoft website) shows the tick count and displays it correctly
int result = Environment.TickCount & Int32.MaxValue;
player.SendMessage("Result: " + result);
but I want to be able to display how long its been up in minutes.
From the MSDN documentation, we can see that Environment.TickCount
Gets the number of milliseconds elapsed since the system started.
You can then convert it to minutes like so:
var minutes = (Environment.TickCount - serverStartTickCount) / 60000; // 1000 ms/s * 60 s/m
Alternatively, you might want to consider storing DateTime.Now when the server starts. Say your class is called Program, you can add this to it:
public static readonly DateTime ServerStartTime = DateTime.Now;
and then do this when the command is run:
var uptime = DateTime.Now - Program.ServerStartTime;
var minutes = uptime.TotalMinutes;
This would allow you to get an accurate uptime when the Environment.TickCount roll over every few weeks, as #Carlos pointed out.
From the reference docs:
A 32-bit signed integer containing the amount of time in milliseconds
that has passed since the last time the computer was started.
So divide by 1000 to get seconds, and then 60 to get minutes.
Note the thing is only 32 bit, so it loops back every few weeks.
Use a TimeSpan.
TimeSpan uptime = TimeSpan.FromMilliseconds(Environment.TickCount);
double totalMinutes = uptime.TotalMinutes;

C# Convert Date To Double

I have written a function in VBA which creates a code from the properties of a file.
I need a developer to do the same in C# on their end.
The developer says it is not possible to do the same in c#.
So in VBA, part of my process is to convert a date to a double. The way VBA does this is to basically count the number of days between the given date and 1 Jan 1900. So 19 Mar 2014 would be a double value of 41,717.
How would I say write a function in C# (not a language I am familiar with) that would convert a date data type to the number of days that have passed since 1 January 1900?
Any help would be appreciated.
Subtracting two DateTimes gives you a TimeSpan. You can just use TimeSpan.TotalDays to get the number of days between two dates:
double days = (DateTime.Today - new DateTime(1900,1,1)).TotalDays;
If the DateTime has a time component it will be represented as fractions of a day, so for example:
// current date and time (16:24:15)
(new DateTime(2014, 3, 18, 16, 24, 15) - new DateTime(1900,1,1)).TotalDays
would give you 41714.6835069444
Note that the result is 2 days different that using CDbl() in VBA since a date in VBA is represented by the number of days since 12/30/1899 rather than 1/1/1900.
Use .net DateTime method ToOADate() wich returns a double representing the OLE Automation date
VBA uses this same format to representa a date as a double.
I got exactly 3 days difference. Which might be because I'm in NZ at GMT + 12.
Or it might be because I was multiplying a double by "TicksPerDay" and .Net doesn't allow for some strange numbers.
DateTime.FromOADate(vbaTime) was the perfect solution for me moving dates between MS Access and C#.
Incidentally, I suspect that this is a result of the "date calculation issue" that Joel Spolsky refered to:
http://www.joelonsoftware.com/items/2006/06/16.html
when discussing Lotus notes compatibility in Excel as the program manager at Microsoft.
How about this, without using OLE Automation:
'get time elapsed since some earlier point in time, such as midnight today
Dim tim As TimeSpan = Now.Subtract(Today)
'calc the time elapsed in fractional seconds
'note that tim.Seconds only provides whole seconds, so add tim.Milliseconds
Dim tsec As Double = tim.Hours * 3600 + tim.Minutes * 60 + tim.Seconds + tim.Milliseconds / 1000

Get Hours and Minutes from Datetime

Out Time :
2013-03-08 15:00:00.000
In Time :
2013-03-08 11:21:03.290
I need to get Hours and Minutes separately for same date from above, when (Out Time - In Time).
How can I do that ?
I think you probably just want:
TimeSpan difference = outTime - inTime;
int hours = (int) difference.TotalHours;
int minutes = difference.Minutes;
Note that Minutes will give you "just the minutes (never more than 59)" whereas TotalHours (truncated towards zero) will give you "the total number of hours" which might be more than 23 if the times are more than a day apart.
You should also consider what you want to do if the values are negative - either consider it, or explicitly rule it out by validating against it.
The Subtract method on the DateTime class will allow you subtract that date from the other date.
It will give you a TimeSpan which will be the difference.
I'll leave it to you to work out the actual code.
http://msdn.microsoft.com/en-GB/library/8ysw4sby.aspx
You can use Hours property and Minutes
link : http://msdn.microsoft.com/en-us/library/system.datetime.hour.aspx

Categories