how to convert a date into both European and American time zones in the same sql server report rdl? - sql-server

I have a report which takes timezone as input parameter, picks date from a table and converts this date to the user selected time zone.
User can select timezones from a dropdown which contains both US and European timezones.
When I select the European timezones, I see #Error in the date cell in the report.
I have no clue what so ever about reports and I need to fix this error in the inherited report.
The conversion is done by a little VB script embedded in the report.
Shared Function ConvertTimeZone(ByVal systemDate As Date, ByVal timeZoneId As String) As Date
Dim timeZoneInfo As TimeZoneInfo
timeZoneInfo = timeZoneInfo.FindSystemTimeZoneById(timeZoneId)
Return (timeZoneInfo.ConvertTimeFromUtc(systemDate, timeZoneInfo))
End Function
If EET is passed as timezone id - I see #Error in the date cell.
Could this be because both European and US timezones cant be used together?
Can someone guide me through this issue?

If EET is passed as timezone id - I see #Error in the date cell
That's because "EET" is not a valid time zone identifier. You can see all of the valid identifiers by examining the output from TimeZoneInfo.GetSystemTimeZones(), which returns a collection of TimeZoneInfo objects. Each one has an Id and a DisplayName. The Id is what needs to be passed in your timeZoneId parameter, while the DisplayName can be shown to your end user in the dropdown list. (You probably don't want to use the StandardName or DaylightName properties, unless you have a specific reason to.)
You are probably looking for the identifier "E. Europe Standard Time". Don't get confused by the name, it's the correct identifier covering both Eastern European Time (EET) and Eastern European Summer Time (EEST). The Microsoft time zone database is a bit strange in that way.
You can also see the valid time zones by running tzutil /l on the command line. Each time zone will emit two lines, where the top line is the display name, and the bottom line is the ID.
EDIT
Another suggestion, VB is case insensitive, but you have your variable named timeZoneInfo, which is the same as the class TimeZoneInfo. This would normally work ok, but I see that you have the lower case form on the ConvertTimeFromUtc method, and it should be upper case. Since this is VBScript, you might not be seeing this error until runtime. Try changing the case, or just use a different variable name so you don't get them confused.
Shared Function ConvertTimeZone(ByVal systemDate As Date, ByVal timeZoneId As String) As Date
Dim tzi As TimeZoneInfo
tzi = timeZoneInfo.FindSystemTimeZoneById(timeZoneId)
Return (TimeZoneInfo.ConvertTimeFromUtc(systemDate, tzi))
End Function
Here's another idea you can check if that doesn't fix it. The input systemDate should have come from your data, which should have DateTimeKind.Unspecified when you examine it's .Kind property. If for some reason you are taking it from DateTime.Now instead, then it would have a DateTimeKind.Local, which would through an exception.
If you still get the error, please see if you can find out what exception or error is actually occurring. Check log files, event viewer, etc.

Related

SSRS date parameter format changes when executing report

I have a report with date parameter. The default value is today() which for this example is 7th of October 2018.
The date in parameter box is displayed in US format (10-07-2018).
When I hit "Show report" day and month in the parameter box switches places (changes to 07-10-2018).
When I hit "Show report" again, they switch places again.
Of course, I would prefer it to be displayed in UK format and stop switching places.
When day >12 then this does not happen.
When I select the date from the calendar, it is even more bizarre. (I have 2 date parameters). The date displayed is in US format (unless day>12 then stays correct) but also switches day and month for the second parameter.
UPDATE: even stranger: using function dateserial(2018,10,7) gives:
7th of October in dataset fileter (correct)
10th of July in Parameter box (default value)
As if thre qas different locale settings for parameters and body of raport.
It concerned all reports on the server and tested on two clients.
Windows server language is Polish (for our purposes may be considered the same as the UK).
Regional settings on the server are Polish.
Regional settings on IE are Polish
Default date format in report builder (one with *) is 07.10.2018 (like the UK)
The language on the report is set to PL-pl
The language on the database is Polish
Microsoft SQL Server and Reporting Services Version 13.0.4224.16
If you format your column the right way (date format) but your language settings (global) are emtpy you get your dates displayed randomly. So you always need, both the language settings and the format for the columns, then the dates will always show like you set them.
Click on the gray area of your report (Report Properties). Then look under Localization > Language. Check if the Language property is empty. If its empty put in your needed date format.
I know this is an old one, but I had the same issue and wanted to update, that for me, the date was giving the same error as you when using the reportbuilder, but was working properly when uploading the report and viewing from report server.
also, in report builder it was just how it was showing the date picker parameter after submitting, it was still using what I originally set

SSRS Date Parameter Mismatching

I have an issue with SSRS where when posting in a DD/MM/YY value via URL string into a Parameter it decides to read the Day value as the Year, the Month as month, but the Year goes into Day value, for example:
I am inputting the date of 30/08/17 via an ERP System which then generates a string to be used as an URL to generate the report, this date value should then go into a parameter called fiAsOfDate which is Date/Time data type, but at this point it is reading the value as 08/17/1930 inside the Parameter list, even though the URL remains at 30/08/17.
This happens prior to the Query being processed, and the fiAsOfDate parameter then gets formatted through to to MMDDYYYY to be processed within the Query, but the issue is specifically when the parameter is having the value loaded from the URL into the parameter value, and I was hoping if anyone could assist me on this please?
I should also add, this original date is coming from an ERP system which will have regional based date formatting, as it is used internationally, so I cannot restrict myself to one input format, and it should be using regional settings, matching that of the Reporting server that it is based on.
Kind Regards,
James W. Acklam.
To avoid regional setting issues you can change the date into a known integer or string format: I use CONVERT(NVARCHAR, YourDate, 112) to get a string '20170830'. The regional settings won't recognize that as a date and so won't auto-parse it into MM/DD/YYYY or DD/MM/YYYY. Of course, you'll need to parse that yourself so you can use it in the report, but at least you know the format.
This issue was down to my own misunderstanding that the DataSource I was pulling data from worked only in DMY format. Converting dates from parameters format to DMY format and processing that through the DataSet's query resolved the issue.

Date from angular(timezone) to server (utc) then utc to Timezone

I have an issue with getting dates back in the right timezone.
Firs at all in the local machine, everything works fine but not in the server: the server is hosted in USA and the clients mostly are in Australia.
So a date is sent from angular app("12/23/2015 11:00:00 AM") to the server, the server store a date as utc in the database, until this point everything is working(I checked and the date is stored in the right utc)
book.StartDateTime = TimeZoneInfo.ConvertTimeToUtc(DateTime.SpecifyKind(book.StartDateTime.Value, DateTimeKind.Unspecified), ToolsHelper.OlsonTimeZoneToTimeZoneInfo(locationDetails.TimeZone)); // book.CreatedDate.Value.ToUniversalTime();
The issue is:
When a client request some dates stored in the database. The date stored in the database is return back to the client like this:
bookview.StartDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.SpecifyKind(bookli.StartDateTime.Value, DateTimeKind.Utc), ToolsHelper.OlsonTimeZoneToTimeZoneInfo(deCompany.TimeZone));
I checked and at this point the date is "12/23/2015 11:00:00 AM" -> the conversion is right in the server(in the server side I put a log),
But in the angular is shown as "12/23/2015 10:00:00 PM"
So apparently the issue is when the date is transferred by the api to the client, maybe when is converted to JSON
I have tried different ways nothing work, I have removed "DateTime.SpecifyKind", I convert the date to string then back to datetime format and nothing seems to work.
What could I do?
A few things:
Your example is not complete, so I can only speculate on some areas. It would be better to show both sides, including how you load and parse the data in Angular, and what the data looks like over the wire.
You shouldn't be sending dates back and forth in a locale-specific format like "12/23/2015 11:00:00 AM". You might use those in your UI, but they're not appropriate over the wire (in your JSON). Instead, you should be using ISO8601/RFC3339, such as "2015-12-23T11:00:00Z". (You probably are already doing this if you're using WebAPI.)
A DateTime object when serialized to ISO8601 format is coupled with the associated DateTimeKind in the Kind property.
If the Kind is Utc, then the ISO8601 string will end with a Z.
If the Kind is Local, then the ISO8601 string will end with the machine-local offset for that timestamp, such as -08:00.
If the Kind is Unspecified, then the ISO8601 string will not have either Z or offset - which means that it cannot unambiguously represent a specific moment in time.
This is ultimately the cause of the error. You're converting the DateTime to another time zone, which leaves it with Unspecified kind, which then gets serialized without an offset - so on the client side that gets interpreted (probably) in the local time zone of the browser.
A better approach is to use DateTimeOffset instead of DateTime. Then you don't have to worry about Kind, and the offset is always present. If you change your bookview.StartDateTime to a DateTimeOffset type, you can do something like this to fix the problem:
DateTimeOffset dto = new DateTimeOffset(bookli.StartDateTime.Value, TimeSpan.Zero);
bookView.StartDTO = TimeZoneInfo.ConvertTime(dto, ToolsHelper.OlsonTimeZoneToTimeZoneInfo(deCompany.TimeZone));
That will ensure that the offset gets persisted in the data.
On the client side, pay careful attention to how the ISO string gets parsed. if it's loaded into a Date object, then it will indeed be converted to the client's time zone. Instead, you might take a look at moment.js for client-side time formatting. In particular, use moment.parseZone to keep the value in the same offset that it was presented. For example:
var s = moment.parseZone("2015-12-31T11:00:00+00:00").format("L LT"); // "12/31/2015 11:00 AM"
In commented code, you also showed a call to DateTime.ToUniversalTime - be very careful with that. If the source kind is Unspecified, it is treated as Local. Therefore, the local time zone of the computer is reflected in the converted value. It's better to avoid ToUniversalTime and ToLocalTime entirely. Use only the conversion methods on TimeZoneInfo.
ToolsHelper.OlsonTimeZoneToTimeZoneInfo isn't something we know about either. But I'll assume it does a CLDR mapping similar to this one. However, if you're working with Olson time zones anyway, the better approach would be to not use TimeZoneInfo at all. Instead, use Noda Time, with it's native support for tzdb time zones.

Javascript time saved incorrectly in sql server table

new Date(moment().year(), moment().month(), moment().day(), vm.newHearing().HearingTime().split(":")[0], vm.newHearing().HearingTime().split(":")[1]).toLocaleString()
The client side value for a date column is 11/5/2013 10:15:00 AM. The time is selected from HTML5 time input control.
When I check in database after saving the entity, it shows me incorrect time value:
11/5/2013 3:15:00 PM
It appears that you are using moment.js, which is fine except you aren't using it properly
Try this instead:
moment(vm.newHearing().HearingTime(), "HH:mm").toISOString()
That will pass the selected time, on the current day, from the user's local time zone, converted to UTC time and in ISO format.
Now that might not be exactly what you want to do. Depending on your requirements, you might instead want this:
moment.utc(vm.newHearing().HearingTime(), "HH:mm").toISOString()
Which is almost the same thing except that it assumes the input time is already in UTC.
Or you might want this:
moment(vm.newHearing().HearingTime(), "HH:mm").format("YYYY-MM-DDTHH:mm:ss")
This one doesn't try to convert to UTC at all.
For all choices, I emit the date string in ISO8601 format. Since you are sending it back to the server, this is the best choice. When you used toLocaleString, that generates a format that is appropriat for display only.

Validating Date Parameter in SQL Server Stored Procedure

I've written a stored procedure that takes in a date parameter. My concern is that there will be confusion between American and British date formats. What is the best way to ensure that there is no ambiguity between dates such as 02/12/2008. One possibility would be for users to enter a date in a format such as 20081202 (yyyymmdd). Is there any way to validate that without using sub strings? Alternatively dates could be entered as 02-Dec-2008(dd-mmm-yyyy), but again verification is not trivial and there are potential issues with users who do not use English.
Further to the first three answers . . . One issue is that I'm expecting this stored proc to be called directly without a front end so validation ouside of the proc is not an option. Is it a good idea to take the day, month and year as separate parameters?
You won't have any problems whatsoever if you'd use parameters in your sproc:
create proc dbo.Sproc
#date datetime
as
...
If you declare the parameter as being of type DATETIME or one of the other typed date/time types in SQL Server, which you should, then there is no ambiguity; it represents a particular date and time. The type of validation you're talking about should happen outside the stored procedure, not inside.
OK from your comments and edit, it appears the issue is with the way people call the SP rather than actually within it. To that end, you simply need to train your users to use sortable date format, i.e.
yyyy-MM-dd HH:mm:ss
And then there is no ambiguity. Anybody who is allowed near a database should be aware of localisation issues and should always be using a non-ambiguous format like this one when entering dates.
I've ended up taking a string paramater for the date and require users to enter the month as a word. I check the input is a valid date by converting it to date. To ensure the month is entered as a word, I use the like comparator to compare the input string with "%Jan%" or "%Feb%" or "%Mar%" etc.
If your proc accepts the date as a datetime parameter then there is little you can do to validate that the desired format is ddmmyyyy and not mmddyyyy. It all depends on how the user entered the date and how it was passed to SQL.
For example: On a web page i could add a parameter like this
command.Parameters.AddWithValue("#mydate",mydateVar.ToString("dd/MM/yyyy"));
OR
command.Parameters.AddWithValue("#mydate",mydateVar.ToString("MM/dd/yyyy"));
And SQL will just insert what its given as long as the string can be cast to a date correctly. It wont know the format you want to use so it will try to cast to its system default format.
A solution i use although it may not be applicable in your situation is to have users enter all dates in whatever frontend you have in the dd-MMM-yyyy format. I can then be sure of the format before i insert into the DB. I use that format everywhere to keep it all the same throughout the app.
You said that you are expecting this stored proc to be called directly without a front end and validation ouside of the proc is not an option.
In that case the users will be inserting data directly, I also believe that in this case it is for internal use only (as the stored proc is going to be called directly)
So I think you have 2 options
if you have disciplined users you can agree on one of the safe formats: ISO yyyyddmm, or ISO8601 yyyy-mm-dd Thh:mm:ss:mmm if you need a time part as well
otherwise take 3 parameters: year, month, year and perform some validation inside the stored procedure
I say take a datetime and train them to use the ODBC canonical form of a date as in this example:
EXECUTE uspMyProc {d '2009-02-11'}
If you take a date that you have to parse, whether it be a string or the year, month and day as separate integer arguments, then you have to deal with days out of range for the month and year. Some functions that take those automatically advance or move backwards the day on you. Thus the trick of sending 0 for the day and getting the last day of the previous month. Others return an error. But handling that stuff yourself is probably not worth reinventing the wheel.
If you absolutely have to because novices will be running it directly (why would novices be running stored procedures directly?), I'd take three separate arguments and pass the concatenated date as a string in the format YYYY-MM-DD through ISDATE to verify the parameters and exit if it isn't valid.

Resources