How to round a DateTime in MySQL? - c#

I want to discretize the DateTime with the resolution of 5 minutes. I did it in C#, but how to convert the following code to MySQL?
DateTime Floor(DateTime dateTime, TimeSpan resolution)
{
return new DateTime
(
timeSpan.Ticks *
(long) Math.Floor
(
((double)dateTime.Ticks) /
((double)resolution.Ticks)
)
);
}

It's a little nasty when you do it with datetime data types; a nice candidate for a stored function.
DATE_SUB(DATE_SUB(time, INTERVAL MOD(MINUTE(time),5) MINUTE ),
INTERVAL SECOND(time) SECOND)
It's easier when you use UNIXTIME timestamps but that's limited to a 1970 - 2038 date range.
FROM_UNIXTIME(UNIX_TIMESTAMP(time) - MOD(UNIX_TIMESTAMP(time),300))
Good luck.

from_unixtime(floor(unix_timestamp('2006-10-10 14:26:01')/(60*5))*(60*5))
+---------------------------------------------------------------------------+
| from_unixtime(floor(unix_timestamp('2006-10-10 14:26:01')/(60*5))*(60*5)) |
+---------------------------------------------------------------------------+
| 2006-10-10 14:25:00 |
+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
you can replace the two 5s with other values

You can look here. This example is a general case for rounding to the nearest X minutes, and is written in T-SQL, but the logic and the majority of the functions will be the same in both cases.

Another alternative:
to get the nearest hour:
TIMESTAMPADD(MINUTE,
ROUND(TIMESTAMPDIFF(MINUTE,CURDATE(),timestamp_column_name)/60)*60,
CURDATE())
Instead of CURDATE() you can use an arbitrary date, for example '2000-01-01'
Not sure if there could be problems using CURDATE() if the system date changes between the two calls to the function, don't know if Mysql would call both at the same time.
changing 60 by 15 would get the nearest 15 minutes interval, using SECOND you can get the nearest desired second interval, etc.
To get the previous hour use TRUNCATE() or FLOOR() instead of ROUND().
Hope this helps.

Have you had a look at the CAST functionality in MySQL?
MySQL Cast
Cast Functions and Operators

Here is another variation based on a solution from this thread.
SELECT DATE_ADD(
DATE_FORMAT(time, "%Y-%m-%d %H:00:00"),
INTERVAL FLOOR(MINUTE(time)/5)*5 MINUTE
);
This solution, unlike ones that use FROM_UNIXTIME, will give the expected value for datetimes that fall within daylight saving time (DST) transitions. (Compare for example 2012-11-03 2:14:00)
Edit - After some quick benchmarking, however, Ollie's first solution appears to perform faster than this. But I still recommend against the FROM_UNIXTIME method.

Related

Why is the conversion from ulong to DateTime returning 0?

I'm trying to convert ULONG to DateTime and as DateTime accepts Ticks as param which are LONG, here's how I do it.
ulong time = 12354;
new DateTime((long)time).ToString("HH:mm:ss");
The result of this is 00:00:00.
I don't understand the result, am I doing something wrong?
P.S. i.Time is not 0, I checked multiple times.
Citing the documentation:
Initializes a new instance of the DateTime structure to a specified number of ticks.
ticks
Type: System.Int64
A date and time expressed in the number of 100-nanosecond intervals that have elapsed since January 1, 0001 at 00:00:00.000 in the Gregorian calendar.
This is 100 nanoseconds which is a super small time unit. So unless your number is larger than 10000000, you don’t even get a single second:
Console.WriteLine(new DateTime((long)10000000).ToString());
// 01.01.0001 00:00:01
So you should really think about what your “time left” (i.Time) value is supposed to mean? Is this really time in the unit of 100 nanoseconds? Very likely not. It’s probably more about seconds or something completely different.
Btw. if the number you have does not actually represent a moment in time, you should not use DateTime. You should use TimeSpan instead. Its long constructor has the same behavior though, but you can use one of the handy static functions to create a time span with the correct unit:
var ts = TimeSpan.FromSeconds(1000);
Console.WriteLine(ts.ToString());
// 00:16:40
Because a tick is 100 nanoseconds, and so 12354 ticks is only 1235400 nanoseconds which is only .0012354 seconds. So your datetime is .0012354 seconds after midnight on 1 Jan in the year one.

Using DateTime for a duration of time e.g. 45:00

I'd just like to know if it is possible to use the DateTime type for durations such as 45:00 (45 minutes) or 120:00 (120 minutes). These values also need to be stored into a Local Sql Server DB. If it is possible, could anyone possibly hint how this could be done using Datetime, or if not just let me know a way it could be done using a different type.
Thank you in advance,
Jamie
You should use the TimeSpan structure
TimeSpan interval = new TimeSpan(0, 45, 0);
Console.WriteLine(interval.ToString());
For the database storing part, you could store the property Ticks because a specific constructor for the TimeSpan structure allows to instantiate a new TimeSpan passing the Ticks value
long ticks = GetTimeSpanValueFromDb();
TimeSpan interval = new TimeSpan(ticks);
I wish to add also that you need a BIGINT T-SQL datatype field to store a long NET datatype
I store durations in seconds in the database and then convert to HH:MM:SS format when comes time to display the data.
Why don't you use TimeSpan instead? You can convert them to Ticks (int), store them in the db and the reverse the process when you need the value.
This is merely a matter of interpretation. SQL Server stores datetime as two four byte integers. One is a signed int count of days from a reference date, the other is an unsigned time of day such that 32bits exactly maps 24 hours. Without the implicit epoch, this isn't a datetime, it's a duration. Nothing prevents you from interpreting it that way.
Of course, it would be more convenient to pick a unit and simply use a float. This is what Windows does, storing datetime as a number of days from a reference date expressed as an 8-byte float (a double).
Personally I don't like "day" as a unit of time. The rotational period of our planet is not constant, and it is necessary to mess about with leap seconds to maintain the illusion that there are 86400 seconds in every day. A better choice is the SI unit, the second, which is defined in terms of repeatable, invariant physical constants.
Better again would be the picosecond, since we could dump the double and use an int64, with all the attendant arithmetical and comparative performance advantages. Depiction in mixed human scale units (yyyy mmm d HH:mm:ss) is already something of a trial. Mapping functions that currently work with fractional days could trivially be scaled to microseconds, although the compensation for leap seconds and leap days would have to be rewritten.
I say picosecond because this is the finest division that fits in 64 bits while encompassing a useful span of time (50,000 years). Femto fits, but fifty years isn't wide enough. I know that eventually there be a year 50K problem but frankly I doubt anyone but archeologists will care about records from 50,000 years ago.

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

Converting a value of more than 59 (seconds) effectively into a DateTime

I am getting 'time played' values which come as an integer in the amount of seconds.
Providing there is less than 60 seconds to be added, it's ofcourse easily done.
However, a lot of the values are more than 59 seconds and therefore cannot easily be converted into a DateTime.
An example of a value would be: 159, which means that the 'time played' is 2 minutes and 39 seconds.
Thanks in advance.
A "number of seconds" shouldn't be stored in a DateTime in the first place. You should use TimeSpan, which makes it easy:
TimeSpan ts = TimeSpan.FromSeconds(159);
You can add a duration of time to any DateTime, of course, but that's a different matter.
(You might also want to look into my Noda Time library if you're doing any significant amount of work with dates and times... the BCL provision is somewhat underwhelming.)
I think you want to use a TimeSpan not a DateTime. Specifically TimeSpan.FromSeconds().
See: http://msdn.microsoft.com/en-us/library/system.timespan.fromseconds.aspx
What you want is a TimeSpan structure.

Disparity between date/time calculations in C# versus Delphi

Delphi:
SecondsBetween(StrToDateTime('16/02/2009 11:25:34 p.m.'), StrToDateTime('1/01/2005 12:00:00 a.m.'));
130289133
C#:
TimeSpan span = DateTime.Parse("16/02/2009 11:25:34 p.m.").Subtract(DateTime.Parse("1/01/2005 12:00:00 a.m."));
130289134
It's not consistent either. Some dates will add up the same, ie..
TimeSpan span = DateTime.Parse("16/11/2011 11:25:43 p.m.").Subtract(DateTime.Parse("1/01/2005 12:00:00 a.m."));
SecondsBetween(StrToDateTime('16/11/2011 11:25:43 p.m.'), StrToDateTime('1/01/2005 12:00:00 a.m.'));
both give
216905143
The total amount of seconds is actually being used to encode data, and I'm trying to port the application to C#, so even one second completely throws everything off.
Can anybody explain the disparity? And is there a way to get c# to match delphi?
Edit: In response to suggestions that it might be leap second related: Both date ranges contain the same amount of leap seconds (2), so you would expect a mismatch for both. But instead we're seeing inconsistency
16/02/2009 - 1/01/2005 = Delphi and C# calculate a different total seconds
16/11/2011 - 1/01/2005 = They calculate the same total seconds
The issue it seems related to this QC 59310, the bug was fixed in Delphi XE.
One will likely deal with Leap Seconds. However, .NET does not as far as I'm aware.
You don't mention how you convert the c# TimeSpan into a number. The TotalSeconds property is a floating point value - perhaps it's a rounding problem in the double to int conversion?

Categories