Storing a time difference in SQL - sql

In my application, I have a database storing a calendar of events:
id | name | date
----+--------------------+--------------------
1 | Birthday Party | 2013-04-27 16:30:00
2 | Dinner Reservation | 2013-03-20 17:00:00
3 | Sunday Brunch | 2013-03-31 11:15:00
When viewing events in the application, users should be able to configure how far in advance from the present moment they wish to view events, stored as a value in the database:
username | datediff
----------+------------------------------------------
user123 | 2 days in advance
goodguy | 93 days in advance
spudly | 365 days in advance
aaaaaa | 17 days, 3 hours, 30 seconds in advance
My question is: what is the best (i.e., most SQL-idiomatic) way to store such a date differential? I could store the time difference as a number in milliseconds, but is there some built-in SQL datatype that is suitable for date differentials, rather than just particular points in time? Is something like DATETIME or TIMESTAMP appropriate for this task?
It must be a relative difference -- for example, for "2 days in advance" I'm not interested in storing a particular date two days in the future, because I'd like the user to see events for the next two days every time he looks at the application.
I'm using Microsoft SQL Server 2008, if it makes any difference.
(This may be a duplicate, but all my search attempts have turned up results about datediff -- which is used to calculate time differences -- but nothing about how best to store time differences.)

Standard SQL has a specific data type for date and time durations: interval. SQL Server doesn't support the interval data type.
DateDiff() returns a signed integer. If you need to store the SQL Server equivalent to a SQL interval, you'll need to store an integer. The integer is a count of the number of datepart boundaries, so you also need to store what kind of datepart boundary the integer refers to. Without the datepart, the signed integer 3 could just as easily mean 3 years or 3 seconds.
As a practical matter, I think I'd rather calculate a timestamp for the reminder, and store that instead of the integer and datepart that define an interval. A timestamp can be indexed and queried much more simply than the integer and datepart. And without the need to support recurring events, I don't see a compelling reason to build a solution more complicated than that.

Related

Excel 5 digit Datetime converted in SQL is 2 days ahead

I have a spreadsheet with Datetimes as follows:
I am importing this file into an application so in Javascript I see the date being brought through as the normal 5 digit datetime code:
So far as I expect... However, when I then try getting this datetime readable in SQL Server, I run the following scripts:
select
CONVERT(varchar(25),cast(28540 as datetime),121),
dateadd(D,28540,0)
And the dates all return PLUS 2 days!
The same happens for all dates I pass through. I could easily just remove 2 from the 5 digit number but I don't want to just do that if there is a rule or reason for this?
Any advice on this is greatly appreciated!
Excel dates are tricky. What they do is count the number of days since Dec 30th, 1899 (and early years are not entirely accurate).
One option is:
dateadd(d, 28540, '1899-12-30')
Demo on DB Fiddle:
select dateadd(d, 28540, '1899-12-30') new_dt
| new_dt |
| :---------------------- |
| 1978-02-19 00:00:00.000 |

How can I calculate the number of minutes per day between a daterange

First off I apologize I do not even know where to start and haven't been able to find anything specific to this particular question.
I have a table with datetimes (start and end) and i need to find a way to get minutes/hours between those days. It could either be a sum of the time on weekdays or a some kind of pivot on each day and grouping by the ID number. I had thought to assign a value to the number of days however the times are random and do not start/end at midnight so I am at a loss as how to approach this.
Here are some examples of the date/time format if that helps.
startdate 2018-12-14 10:53:01
enddate 2018-12-27 11:50:00
Any helps or hints would be greatly appreciated!
Edit
forgot to include I am working in SQL Server (SSMS)
Editing For Additional Clarification
Here is a sample date range with an ID number, I wanted to keep it simple.
|ID number| start time |end time
|1 |12/14/2018 10:53|12/17/2018 12:00
here is what I'm trying to achieve (the separation of each date range/ID #)
ID number| start time |end time |mins|
1 | 12/14/2018 10:53|12/14/2018 23:59|786 |
1 | 12/15/2018 0:00 |12/15/2018 23:59|1439|
1 | 12/16/2018 0:00 |12/16/2018 23:59|1439|
1 | 12/17/2018 0:00 |12/17/2018 12:00|960 |
The MINUTE parameter of the DATEDIFF function can be used to determine the difference in minutes between two datetime columns. As below, the second parameter is the start date and the third parameter is the end date, with the result being the amount of time in the specified interval (days, minutes, etc.) from the start to the end date. If you need to find the number of hours between these two columns the HOUR parameter can be used for this. Grouping can be performed as well, as in the second example.
DATEDIFF:
SELECT DATEDIFF(MINUTE, StartDateColumn, EndDateColumn)
DATEDIFF with Grouping and Aggregation:
SELECT ColumnA, SUM(DATEDIFF(MINUTE, StartDateColumn, EndDateColumn)) as DifferenceInMinutes
FROM YourSchema.YourTable
GROUP BY ColumnA

Converting Time into Minutes in Pentaho (PDI Script)

I want to calculate sum of activity time(HH:mm:ss) for various transactions in PDI. For example, consider 3 activity times: 1) Activity 1 - 01:22:03,
2) Activity 2 - 01:10:11 and 3) Activity 3 - 00:22:20. The sum of all this time should be 02:54:34 but the result displays negative value. How would I improve it?
I ran into your issue (and the solution) almost by accident. It's worth explaining in a bit of detail.
Date fields are not meant for durations. They define instants. If you define a date field without its date part you're actually defining it as an instant on 1 Jan 1970, which is Unix time's start.
So, if you take your first timestamp, when you set 01:22:23 as a date field you're actually setting it to be "1 Jan 1970 01:22:23". You'd expect this field to return 4923 it's value in seconds (e.g., using getTime() on Javascript). This would work out nicely for your calculations; you could then add them up, and re-format to display.
However, if you don't specify the Timezone when setting the date value, then the date field will use your LOCAL timezone settings to define that time.
So, if you're in NY timezone, defining 01:22:23 as a Date field with format HH:mm:ss returns "31 Dec 1969 6:22:23 UTC", which returns 22923 in seconds.
If you're in Paris or another city which was ahead of UTC on 1 Jan 1970, some or all of your durations may return negative values.
The reason I say I ran into it by accident is because I'm based in London, which should be on UTC in the winter. However, oddly, that was not the case in 1970 (see UNIX timestamp(0): Europe/London returns UTC+1)
So, when calculating the timestamps in London timezone, I got:
Local time, seconds in Unix time
1:22:03, 1323
1:10:11, 611
0:22:20, -2260
These numbers add up to -326.
My suggestion:
Don't define durations as dates, or timestamps; that's not what they are. Durations are time intervals. A 1h duration is worth the same regardless of the year, day or timezone you measure it in.
Instead, just parse the values in a javascript step and do the math without resorting to date parsing.
Hacks to get around the problem (which I don't recommend):
explicitly set the timezone as +0000 when converting the fields to dates;
change your computer's timezone to UTC.

converting different timezones to a unique time zone using hive

I have data in this way
' date | Col 1
----------------------------------------
2014-07-07 00:02:15.089-07 | 10
2014-07-07 00:08:15.069-08 | 20
2014-07-10 00:04:17.079-09 | 40
2014-07-08 00:07:15.089-06 | 30
The 07/08/09/06 at the end of the date string represents the time zone. I am trying to get a avg of column. But first i need to convert all the different time zones in to a unique time zone. I need to convert all the date strings to UTC and then do an average of col 1 for different days or hours. I thought of using substrings, but doesn't help. Any help would be appreciated, thanks a lot.
I think you can use UDF (User defined functions) for the purpose.
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF

Sql Query To get data

i have a table called DrTimings ,in which Doctors time for each day is this.
DrID(int identity) StartTime(DateTime) EndTime(DateTime)
1 3/31/2009 8:00:00 AM 3/31/2009 10:30:00 AM
I have another table called TimeList which contain 3 fields
SlotID SlotStartTime(varchar) SlotEndTime(varchar)
1 8:00AM 8:15AM
2 8:15AM 8:30AM
3 8:30AM 8:45AM
and goes on till 7:00PM
I have another table DrDutyDetails in which DrTiming is set for whole month like this.
DrID StartTime EndTime DateOfAllocation
1 4/5/2009 8:00:00 AM 4/5/2009 9:30:00 AM 4/5/2009 12:00:00 AM
2 4/12/2009 8:00:00 AM 4/12/2009 9:30:00 AM 4/12/2009 12:00:00 AM
likewise
I have another table called AppointmentSchedule which gets filled when patient requests appointment
AppointmentID SlotID AppointmentDate
1 1 4/5/2009
2 3 4/12/2009
i have a appointment schedule form in which i selects DrID and Appointment date.Then slots corresponding to date that has not been in Appointmentschedule,but slots should be in between starttime and endtime that in DrTimings and in TimeSlots should get filled in a dropdownlist.I need a query to implement this.
for eg:If Patient enters '4/5/2009' Then slots other than 1 and 3 but biw DrTimings i want to get.
Similarly i want to search by time.Means if Patient enters any time b/w DrTimings for eg:8:30AM,Then available first date has to be displayed in textbox
You are going to need to look at doing some Casting/COnverting of date values. This MSDN article gives you a bit of information on what you need to work with.
There are a number of ways that you can do this, but ideally you can do something like CONVERT(VARCHAR(50), StartTime) to get the fully formatted time. Then, since you know that the ending format of that is 08:00AM, you can do a RIGHT(CONVERT(VARCHAR(50), StartTime), 7), which will get you just the time value.
Now, with that you know how to manipulate the date into parts, you can from here, do the various things needed to query your items.
For comparison sake, I would be storing the "TimeList" data as DateTime values, that way you can use standard time comparisons to actually allow you to use functions such as "Between" and similar. You could store them as 1/1/1900 08:00AM or similar. But this would require a data model change. If you want some helpful SQL for this type of thing, here is a great article on "Essential SQL Server Date, Time, and DateTime Functions".