TimeSpan calculation is different between TimeOnly and DateTime - c#

I'm having a hard time understanding why this is happening or even if this should be happening. If I calculate the TimeSpan between two DateTime objects (same date, different times) and compare it to the same calculation using two TimeOnly objects I get different results.
var start = new DateTime(1, 1, 1, 14, 0, 0);
var end = new DateTime(1, 1, 1, 10, 0, 0);
Console.WriteLine(end - start); // Prints -4 hours
However...
var start = new TimeOnly(14, 0, 0);
var end = new TimeOnly(10, 0, 0);
Console.WriteLine(end - start); // Prints 20 hours???
Isn't the span between starting at 2pm and ending at 10am always a span of -4 hours? Interestingly enough if I take the second one and do Console.WriteLine(end.ToTimeSpan() - start.ToTimeSpan()); I end up with -4 hours.
This feels like an error on TimeOnly's part but I don't know. Here is a fiddle I did comparing results between NodaTime, System.DateTime, converting System.TimeOnly to TimeSpan, and System.TimeOnly.

Related

AlarmManager fires just after five seconds almost immediately

I am using Xamarin Android to issue notification after 10 seconds using alarm manager but whatever time I set the notification is fired just after 5 seconds. I've tried reading the other posts from which I understood that I had to set milliseconds from after 1970, but didn't work
Attempt 1
Intent alarmIntent = new Intent(Application.Context, typeof(AlarmReceiver));
alarmIntent.PutExtra("message", "This is my test message!");
alarmIntent.PutExtra("title", "This is my test title!");
PendingIntent pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
AlarmManager alarmManager = (AlarmManager)Application.Context.GetSystemService(Context.AlarmService);
//alarmManager.Set(AlarmType.Rtc, SystemClock.ElapsedRealtime() + 30 * 1000, pendingIntent);
Java.Util.Calendar calendar = Java.Util.Calendar.Instance;
calendar.Set(CalendarField.HourOfDay, 21);
calendar.Set(CalendarField.Minute, 41);
alarmManager.Set(AlarmType.RtcWakeup, Calendar.GetInstance(Java.Util.TimeZone.Default).TimeInMillis+10000, pendingIntent);
Attempt 2
DateTime dtBasis = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); // Android times are quoted as milliseconds since start of 1970
alarmManager.Set(AlarmType.RtcWakeup, (long)DateTime.Now.AddMinutes(1).ToUniversalTime().Subtract(dtBasis).TotalMilliseconds, pendingIntent);
The standard method of getting the milliseconds since the epoch (01/01/1970) within Android is to use the System.currentTimeMillis() method. Therefore you would likely want to try setting the second parameter for alarmManager.set() to be System.currentTimeMillis() + 10000.
The C# equivalent would be to create a DateTime object representing the epoch
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
And then subtract it from the DateTime.UtcNow object to get a TimeSpan object from it
TimeSpan tsEpoch = DateTime.UtcNow.Subtract(epoch);
Finally, to retrieve the time in milliseconds, cast the timespan's TotalMilliseconds property to a long.
long milliSinceEpoch = (long) tsEpoch.TotalMilliseconds;
With that you simply add 10000 to that value and that should give you the result you are looking for.
This also helps in a great way
Java.Util.Calendar calendar = Java.Util.Calendar.Instance;
calendar.Set(CalendarField.HourOfDay, 20);
calendar.Set(CalendarField.Minute, 57);
alarmManager.Set(AlarmType.RtcWakeup, calendar.TimeInMillis,pendingIntent);

DateTime of packet from Seconds and Microseconds

I have class that open Pcap fileand have this 2 members: Seconds and Microseconds (both int).
How can i create from this 2 fields DateTime ?
This is what i have try:
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, packet.Seconds);
And got this error:
Hour, Minute, and Second parameters describe an un-representable
DateTime.
Code:
var dateTime = new DateTime(1970, 1, 1).AddSeconds(packet.Seconds).AddTicks(packet.Microseconds * 10);
The problem is that the seconds parameter in that constructor must be between 0 and 59 inclusively. What you really want is 1970-1-1 plus the number of seconds.
var dateTime = new DateTime(1970, 1, 1).AddSeconds(packet.Seconds).AddSeconds(packet.Microseconds / 1000000.0);

Converting the date within the places.sqlite file in Firefox to a DateTime

I am having some trouble converting a date found in the file that stores browser history to a normal DateTime.
The file is located at: C:\Users[username]\AppData\Roaming\Mozilla\Firefox\Profiles[profilename]\places.sqlite
The table in question is: [moz_places]
The column is: [last_visit_date]
I've tried using the unix epoch and webkit format(like chrome uses), but neither are giving me the results I expect.
Here is my Unix conversion(not working):
public static DateTime FromUnixTime(long unixTime)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return epoch.AddSeconds(unixTime);
}
This is my webkit conversion code: (Also not working for these dates, it works with chromes webkit dates)
public static DateTime ConvertWebkitTimeToDateTime(long ticks)
{
//Set up a date at the traditional starting point for unix time.
DateTime normalDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
//Subtract the amount of seconds from 1601 to 1970.
long convertedTime = (ticks - 11644473600000000);
//Devide by 1000000 to convert the remaining time to seconds.
convertedTime = convertedTime / 1000000;
//Add the seconds we calculated above.
normalDate = normalDate.AddSeconds(convertedTime);
//Finally we have the date.
return normalDate;
}
So what's the deal with these dates Firefox is storing? Here are a couple sample dates that should all be around today's date or yesterday's.(about 10/17/2013)
1373306583389000
1373306587125000
1373306700392000
Any help or documentation links would be awesome, thanks.
Unix timestamps are measured in seconds.
These values are larger by a factor of one million, i.e., they are using microseconds:
> select datetime(1373306583389000 / 1000000, 'unixepoch');
2013-07-08 18:03:03
Solution in C#:
public static DateTime FromUnixTime(long unixTime)
{
unixTime = unixTime / 1000000;
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return epoch.AddSeconds(unixTime);
}
CL. was correct in that this is simply the millisecond value from the Unix epoch.
Solution in SQL:
Here is a resource that explains his solution in greater detail:
https://support.mozilla.org/en-US/questions/835204

Formatting a TimeSpan to look like a time zone offset

How can I format a TimeSpan object to look like a time zone offset, like this:
+0700
or
-0600
I'm using GetUtcOffset to get an offset, and its working, but its returning a TimeSpan object.
If you're using .Net 4.0 or above, you can use the ToString method on timespan with the hh and mm specifier (not sure if it will display the + and - signs though):
TimeSpan span = new TimeSpan(7, 0, 0);
Console.WriteLine(span.ToString("hhmm"));
If not, you can just format the Hours and Minutes properties along with some conditional formatting to always display the + and - signs:
TimeSpan span = new TimeSpan(7, 0, 0);
Console.WriteLine("{0:+00;-00}{1:00}", span.Hours, span.Minutes);
Reference for TimeSpan format strings: http://msdn.microsoft.com/en-gb/library/ee372287.aspx
Reference for numeric format strings and conditional formatting of them: http://msdn.microsoft.com/en-us/library/0c899ak8.aspx
Try something like:
var timespan = new TimeSpan(-5,0,0); // EST
var offset = String.Format("{0}{1:00}{2:00}",(timespan.Hours >= 0 ? "+" : String.Empty),timespan.Hours,timespan.Minutes);
I add the + when the number is non-negative (for negative numbers a - should be output).
This code:
var timeSpan = new TimeSpan(2, 30, 0);
Console.WriteLine(new DateTimeOffset(2000, 1, 1, 1, 1, 1, timeSpan).ToString("zzz"));
Console.WriteLine(new DateTimeOffset(2000, 1, 1, 1, 1, 1, -timeSpan).ToString("zzz"));
outputs:
+02:30
-02:30
I think you could use this:
String.Format("{0:zzz}", ts);

c# - Substracting two times returns negative value

I'm having problems when I'm trying to substract hr2 with hr1 in a specific situation, for example, when hr1 = 13:00 and hr2 = 15:00, ok, the result is 02:00.
But when the values are: hr1 = 22:00 and hr2 = 02:00, the result is 20:00.
The result should be 04:00.
TimeSpan ts1 = hr1.Subtract(hr2).Duration();
TextBox1.Text = ts1.ToString();
How can I solve this problem?
I understand what you want, but how you currently try to achieve it makes no sense. 22 hours minus 20 hours is 2 hours, which is correct.
You probably want this:
new DateTime(1, 1, 2, 2, 0, 0) - new DateTime(1, 1, 1, 22, 0, 0)
You don't want to subtract TimeSpan's, you want to subtract dates (fake dates in this case).
Invoking Duration() will always result in a positive TimeSpan. The problem is coming from the fact that you are discarding days in your calculation. 22:00-02:00 is 20:00. I believe you are expecting it to be 04:00 because 02:00 represents "tomorrow." If that is what you want, you will need to calculate 22:00-(02:00+24:00) which will give you -04:00, which will become 04:00 when you invoke Duration().
You are trying to subtract two "spans", or durations, of time--not fixed points in time. What your code is currently saying is, I want to subtract two hours from twenty hours (which is indeed twenty hours). Instead, you need to use DateTimes. The hard part is going to be deciding the date for your timespans. I would rework the code to use DateTimes and preserve the "moments" in time that you are actually attempting to calculate.
Edit: Converting from a TimeSpan to a DateTime can cause you to lose information that affects the outcome of the result:
var ts1 = new DateTime (1, 1, 1, hr1.Hours, hr1.Minutes, hr1.Seconds, hr1.Milliseconds) -
new DateTime (1, 1, 1, hr2.Hours, hr2.Minutes, hr2.Seconds, hr2.Milliseconds);
is different than:
var ts1 = new DateTime (1, 1, 1, hr1.Hours, hr1.Minutes, hr1.Seconds, hr1.Milliseconds) -
new DateTime (1, 1, 2, hr2.Hours, hr2.Minutes, hr2.Seconds, hr2.Milliseconds);
or:
var ts1 = new DateTime (1, 1, 2, hr1.Hours, hr1.Minutes, hr1.Seconds, hr1.Milliseconds) -
new DateTime (1, 1, 1, hr2.Hours, hr2.Minutes, hr2.Seconds, hr2.Milliseconds);
Which is why you need to maintain the "point in time" with a DateTime.

Categories

Resources