Editting database dates from nvarchar to datetime - c#

Basically I have been tasked with editing the company database for dates field known as 'CreateDt'.
However the dates with in this field are stored in numerous amounts of formats which need to be converted into one, some examples are shown below;
29/01/2001 08:51:56
29/01/2001 12:09:07
05/06/2002
30/01/2001 11:48:53
31/01/2001 09:30:12
11/12/2014
12 December 2014
15/12/2014
15/12/2014
15 December 2014
15/12/2014
I have previously tried SQL server to convert however I have encountered problems when day and month values are less than 13 and dates are changing from
for example
11/12/2014
to
21/11/2014
Would anyone have C# code which would enable me to format all dates accordingly

There is no such code because simply put, a computer cannot do, what a human cannot define.
11/12/2014
Can you tell me whether that is "November 12th" or "11th of December"? Probably not and that's not surprising. But neither can a computer.
Your best bet is to gather all formats that you think are applicable. For example for the value above, you need to decide which format is correct and which value you want to get. Then convert all your data with those few formats.

Related

convert a C# datetime object into Excel date format

I need to convert a C# datetime object into the dreaded Excel date format:
https://datapub.cdlib.org/2014/04/10/abandon-all-hope-ye-who-enter-dates-in-excel/
i.e. number of days since 1 Jan 1900 expressed as a floating point number.
Is there any way to do it without resorting to DIY code?
I need it in order to create Excel-friendly CSV exports
Googling around I didn't find anything useful except that good blog post
Excel dates use the OLE Automation date format. You can retrieve it with DateTime.ToOADate
OA Dates are a double whose integer part is the date offset from 30 December 1899 (ie earlier dates are negative) and fractional part is the time divided by 24.
This type was used a lot in the COM/VB6 days. Nowadays it's needed for Excel and when you need to call COM APIs that expect dates or variants with a date content.
You can use following method to convert from Excel Date back to C# DateTime
return DateTime.FromOADate(SerialDate);

Generating DateTimeOffsets for a 'local' time range

I'm unsure how best to approach a date/time problem in C#. I have a dataset which lists the working hours for a set of people. Basically, 'person X works 09:00 to 17:30, Monday-Friday'. Basically two TimeSpan-s, which are assumed to be local times for any given date. From this, I need to be able to create two DateTimeOffset-s for any day of the year for a given locale.
For example, if I wanted to generate the UK-based DateTimeOffset for the following dates, I'd get the following results:
2015-01-01: From 2015-01-01T09:00:00+00:00, to 2015-01-01T17:30:00+00:00
2015-07-01: From 2015-01-07T09:00:00+01:00, to 2015-01-07T17:30:00+01:00
Obviously the difference is just the timezone - the first is GMT, the second is BST. A working day isn't normally affected by time zone changes. This is dependent on the date given.
I need to be able to do this for any specified country / region, including those whose timezones change (as demoed above).
If it matters, this will be .NET on Windows.
Thanks for any help.

Converting IBM iSeries DB2 decimal date types into DateTime object

I'm working on a program to import data from an IBM iSeries server into an MSSQL 2008 R2 database. Unfortunately, some developer long ago decided to store dates as a decimal type, effectively breaking the CYYMMDD format being used to store the dates.
For example, in that format, August 1st, 1995 would be stored as: 0950801. However, what's actually being stored in the database is 95081, which obviously throws an exception if I try to convert it to System.DateTime.
If it were a simple matter of missing a leading 0, I could easily add that to the string before trying to convert it. However, there are several (thousands, really) of dates that are only 3 or 4 digits, which I really don't know what to make of. For example, there's a date stored as 1128. I don't know what to make of that at all. If I just tack on 3 leading 0's to that and convert it, it produces an obviously incorrect date.
So, does anyone know a reliable way to parse these dates? Either directly through through SQL select statements, or doing some manipulation in C#? Or am I just to assume 3 and 4 digit dates were never entered correctly in the first place, and just discard such dates?
I would suggest looking at the programs (and particularly any change Comments [assuming they exist]) that insert / update the Table (Query DB2 for this). The change Comments will hopefully tell you if the Date format was changed (e.g. Y2K) and why.
Also looking at any program that read the DB, there may be special code to handle the Date. There may be code to determine the Date Format.
The 95081 could also be an Ordinal date (YYDDD) where DDD is the Day of the Year. See Ordinal or Julian-Date. These where Dates popular at one stage.
I would guess the DB-Field was originally YYMMDD with no Century. The format was probably changed to CYYMMDD for Y2k. Dates like 1128 (and 221) are probably YYMMDD dates that where created before the Y2k changes where Implemented (or where missed in the original y2k implementation and changed later).
After a lot of trial and error, I think I've found the solution.
SELECT
(CASE WHEN INT(SUBSTR(DIGITS(DTPSTD), 1,2)) > MOD(YEAR( CURRENT DATE),100)
THEN DATE(CONCAT(CONCAT(CONCAT(SUBSTR(DIGITS(DTPSTD), 3,2), '/'), CONCAT(SUBSTR(DIGITS(DTPSTD), 5,2), '/')), CONCAT('19', SUBSTR(DIGITS(DTPSTD), 1,2))))
ELSE DATE(CONCAT(CONCAT(CONCAT(SUBSTR(DIGITS(DTPSTD), 3,2), '/'), CONCAT(SUBSTR(DIGITS(DTPSTD), 5,2), '/')), CONCAT('20', SUBSTR(DIGITS(DTPSTD), 1,2))))
END) AS TransactionDate
FROM TABLE_NAME
WHERE CUSTOMER_ID = 1
DTPSTD is "Date Posted"
As far as I can tell, this works for any date in 1900 or 2000, but wouldn't work for dates older than 1-Jan-1900. In my case that's fine, since I don't have any dates older than 1920 or so stored.
Decimal CYYMMDD was a standard IBM format, where C was zero for 1900's and 1 for 2000's. This dates back to the S/38 (around 1982) or perhaps earlier. But I don't recall seeing them use it prior to the S/38, which was the predecessor to the AS/400 and iSeries.
I suggest creating a user-defined function in DB2 to convert your decimal dates into ISO date values. DB2 for i will cache results of DETERMINISTIC functions, so the function doesn't have to be recomputed every time it sees a date value it has processed before.
Update
Here is an example I adapted to convert a packed decimal(8,0) value in ccyymmd or yymmdd format into a DB2 Date:
CREATE OR REPLACE FUNCTION
Cvt_Dec8cymd_to_Date ( dtin dec(8,0) )
returns date
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC -- caches results
NO EXTERNAL ACTION
RETURNS NULL ON NULL INPUT
NOT FENCED
SET OPTION DBGVIEW = *SOURCE
prc: BEGIN NOT ATOMIC -- don't rollback on error
DECLARE ans date;
DECLARE cymd dec(8,0);
-- add declarations for conditions and handlers here
SET ans = null;
CASE
WHEN dtin > 999999 THEN -- more than 6 digits given
set cymd = dtin;
WHEN dtin < 400000 THEN -- yr < 40 means 2000's
SET cymd = 20000000 + dtin;
ELSE -- yr >= 40 means 1900's
SET cymd = 19000000 + dtin;
END CASE;
--convert to date
SET ans = date( insert(insert(digits(cymd),7,0,'-'),5,0,'-') );
RETURN ans;
END prc
;
It is simple logic, without error handling for invalid values.
Someone else may have a better example, or might improve this one.

How to specify a 12-hour time format in SQL Server 2008

I am using SQL Server 2008 and I have a database file (mydata.mdf) in which I have a column in one of the table and that column has the datatype (Time) .
I added this database file to my WPF-C# project (using VS2010) , but I had a problem and its as follows :
This (Time) column treats time in 24-Hours system , but I want to use (12-Hour) system in my application , so is there a way to define a 12-Hour system time in SQL server2008 .
and if there isn't , what do you think is the best way to handle that ???
Pleeeeeeeeeeease help me ASAP because I'm in a hurry and I can't figure it out ...
The time in the database is not "formatted". It is represented in some internal format (which you can Google for but shouldn't care about) that allows it to represent each moment in the day, to the supported level of precision.
The values are only formatted when your application converts them to strings for the purpose of displaying them to the user, and you have full control over this.
So if you have read a time into an instance of the CLR DateTime class, you can display as a 12-hour time (omitting the date) with value.ToString("h:mm:ss tt"). Custom formatting options are listed here.
The answer is you can't really, but don't worry, it's not a problem. Format the date in your C# code.
The point is that a date and time is an absolute value, which is what you want SQL to store, then 12 hour vs 24 hour clock is merely a display detail, eg, 13:00 and 1:00pm are equivalent, don't worry about how SQL stores it, then in C# use the following to display it:
DateTime myDateTime = GetTheTimeFromSomeMethod();
myDateTime.ToString("h:mm:ss tt");
There are lots of guides, This is a good one, but there are plenty of others eg this one
Does it have to be formatted from the database? C# and WPF both provide many built-in date format options. For example, check out the ContentStringFormat property on a Label.
If you must do it in the database, here is a messy workaround which will work
It formats the date as a string using a 12h clock, then removes the date part of it
select right(convert(varchar, cast('1/1/2010 23:59:59' as datetime), 100),
charindex(' ', reverse(convert(varchar, cast('1/1/2010 23:59:59' as datetime), 100)))-1)

Using SQL Server 2008 Date Data Type to Store Year

Does it make any sense to store just a year in the new Date SQL type in SQL 2008? My boss wanted this but we're prompting the customer to enter year optional in a web form..just 4 integers. I don't see why we'd use Date datatype as that also includes day and month and I've already got those seperated out into int fields in our DB table.
Year is optional on our web form, so if they only enter Month and Day, it makese no sense to me to store this in a date type of field because year will have to be something abritrary. I guess we could do 01-16-1900 if they didn't enter year and then we'd have just day and month..but whatever, to me that's a hack. I'd rather seperate all 3 into seperate fields only because we have one of those values (year) as optional. I don't see that we'll ever require year because it's for a birthdate and we already discussed that would piss off customers if we required year anyway.
No, This makes no sense. It will result in more space in the database, and will also add unnecessarily any code where you are just looking for the year. You'll have to use DatePart() in each query or extract the year in code. Either approach hurts performance.
But if your boss told you to do it, then you should probably do it. I wouldn't make an issue of it. What's your boss's reasoning?
Correction
I retract the portion of the answer above that says "more space in the database". The performance savings I was referring to are in the conversion to query by year.
Don't over think this. Just use the Date type and be done with it.
NOTE:
Taking into account Ron's answer, storing each date component separately is a step backwards in time. You should really always take advantage of the tools given to you. The Date type is a first class citizen in any .NET language.
Using the date will save space if you have not considered that.
http://msdn.microsoft.com/en-us/library/bb675168.aspx
If there's no reason to put the separate day/month int columns into a Date column, I don't see why an optional year should be stored as a date.
Something makes me want to see the month/day columns as Dates too...but I like the other logic of "don't overthink this" as well...
Personally I'd store all 3 values (month, day, year) as a date in the date field - defaulting the year if they don't enter it. That way you have automatic validation on the months and days being valid ... except for Feb 29 and no year, since the date math won't know if it was a leap year or not.
Storing them as ints means you have to do all that validation yourself.

Categories