Is there a way to change the default format of a date in Postgres?
Normally when I query a Postgres database, dates come out as yyyy-mm-dd hh:mm:ss+tz, like 2011-02-21 11:30:00-05.
But one particular program the dates come out yyyy-mm-dd hh:mm:ss.s, that is, there is no time zone and it shows tenths of a second.
Apparently something is changing the default date format, but I don't know what or where. I don't think it's a server-side configuration parameter, because I can access the same database with a different program and I get the format with the timezone.
I care because it appears to be ignoring my "set timezone" calls in addition to changing the format. All times come out EST.
Additional info:
If I write "select somedate from sometable" I get the "no timezone" format. But if I write "select to_char(somedate::timestamptz, 'yyyy-mm-dd hh24:mi:ss-tz')" then timezones work as I would expect.
This really sounds to me like something is setting all timestamps to implicitly be "to_char(date::timestamp, 'yyyy-mm-dd hh24:mi:ss.m')". But I can't find anything in the documentation about how I would do this if I wanted to, nor can I find anything in the code that appears to do this. Though as I don't know what to look for, that doesn't prove much.
Never mind :'(
I found my problem. I was thinking that I was looking directly at the string coming back from the database. But I was overlooking that it was reading it as a Timestamp and then converting the Timestamp to a string. This was buried inside a function called "getString", which is what threw me off. I was thinking it was ResultSet.getString, but it was really our own function with the same name. Oops. What idiot wrote that function?! Oh, it was me ...
Thanks to all who tried to help. I'll give you each an upvote for your trouble.
I believe the table columns are specified differently. Try these variants:
timestamp
timestamp(0) no millis
timestamptz with timezone
timestamptz(0) with timezone, no millis
With which client are you running the select statements? Formatting the output is the application's responsibility, so without knowing which application you use to display the data, it's hard to tell.
Assuming you are using psql, you can change the date format using the SET command:
http://www.postgresql.org/docs/current/static/sql-set.html
Which is essentially a way to change the configuration parameters. The ones that are responsible for formatting data are documented here:
http://www.postgresql.org/docs/current/static/runtime-config-client.html#RUNTIME-CONFIG-CLIENT-FORMAT
Daniel tells me to post my findings as an answer and accept it to close the question. Okay.
I found that the date format I was seeing that did not include a time zone was not what was coming directly from Postgres, but that there were a couple of function calls that I was missing that converted the incoming date to a java.util.Timestamp, and then from the java.util.Timestamp to a String. It was in this conversion from the Timestamp to the String that the time zone was defaulting to EST.
In my own humble defense, my mistake was not as dumb as it may sound. :-0 We had the execution of the query in a subclass that read the results into a List, which we do to allow modification of the query results before output. (In this case we are adding a coule of columns that are derived from the stored columns.) Then we have a set of functions that resemble the JDBC functions to pull the data out of the List, so a calling program can easily switch from processing a query directly to processing the List. When I was wrestling with the date format problem, it just didn't register on me that I wasn't looking at "real JDBC", but at "simulated JDBC" calls.
Related
I have written a program that logs events into a db file as they happen using SQL statement. Whenever I open the table to view, I specifically request the dataset in descending order based on ALARM's date and time. It seems to work only for part of the table. I am using SQLite3 and my program is written in delphi or Pascal.
Here is the SQL statement:
SELECT *
FROM Alarms
ORDER BY datetime(ALARMTIME) DESC
Here is a snapshot of the table. Pay attention to the red arrows. That's where Alarm's date and time doesn't follow descending order. I don't know why this is happening.
I'm not sure how you created your date/time string in your database since that information wasn't given in the question. However, according to the documentation for the datetime() function, the format you have of MM/DD/YYYY HH:MM:SS xx is not one of the accepted formats. In fact, if you do SELECT datetime('1/23/2018 01:40:00 PM') at an SQLite prompt, you get NULL. Whereas, if you use an acceptable format, you do not: SELECT datetime('2018-01-23') gives '2018-01-23 00:00:00'.
So I think the solution is to write the ALARMTIME field using datetime('now'), which does yield a format accepted by datetime(). If you need to sort based upon the format you have now, you can't do it with datetime(). You'd need to reformat the field using string functions to get it in a form you could do a string compare with (e.g., as is done here).
The OP has indicated in a comment that the ALARMTIME is set using the following Pascal code:
FieldByName('AlarmTime').AsDateTime := now;
There's no guarantee that Pascal is going to use a date/time string format in this context that is compatible with SQLite's datetime() function. So Pascal date/time formatting functions can be used to create a format more specifically acceptable by SQLite's datetime(). Then you'd use something like:
FieldByName('AlarmTime').AsString := FormatDateTime('YYYY-MM-DD hh:nn:ss',now);
Now this will change the default view of the date to YYYY-MM-DD .... If you still want your view of the table to show MM/DD/YYYY... then you'll either need to go back to my prior comment about processing the string on the fly in the comparison for sort, or write a little view formatting code so that it displays in a format that's different than what is stored internally, which is a common view/model separation technique.
If you can write your original ALARMTIME format as MM/DD/YYYY and make sure you pre-pad with zeroes (e.g., 01/09/2018 not 1/9/2018) then you can use SQLite's substr function:
SELECT * FROM Alarms
ORDER BY (substr(ALARMTIME,7,4)||substr(ALARMTIME,1,2)||substr(ALARMTIME,4,2)||substr(ALARMTIME,11)) DESC
And you would create your ALARMTIME using this:
FieldByName('AlarmTime').AsString := FormatDateTime('dd-mm-yyyy hh:nn:ss', now);
The above solutions are fairly generic. Depending upon the client library you are using (which you have not specified), there may be another more suitable approach to solving the problem.
You cannot do, for example, SELECT * FROM Alarms ORDER BY ALARMTIME DESC and get an accurate sort since, for example, the date 12/1/2018 would come after 2/1/2018 in that sort ordering even though 2/1/2018 is later in time. This is because 2 follows 1 in the ASCII collating sequence.
If you need to keep your current ALARMTIME string format and not change how you're saving it, which is somewhat free form m/d/yyyy in which the day or month can have one or two digits, you're going to have a bit of work to do in order to sort it if your client library doesn't support some helpers in this regard. Perhaps your only other option would be to use a custom SQLite function. These are written in C and compiled and linked with SQLite. You'd have to find one already written, or write your own.
I have data stored on a SQL Server in a country that is GMT + 2. So for instance, a DateTime value is something like 1/1/1800 12:00:00 AM.
Now, I have a C# console app, that is running on a server in UK. The C# is reading those values from the remote database. However, the date received are 2 hours less, for instance: 31/12/1799 22:00:00.
I changed culture to en-US, the only thing that changed was the printing of 10:00:00 PM instead of 22:00:00
Any idea why the date values are being "auto-converted" to locale timezone instead of keeping the values as is?
Thank you
Regards
The problem you're experiencing is not related to the culture on your computer, it is related to a conversion of timezones.
When initializing the connection - there's a negotiation happening between you and the server that tells the server the time zone of your location, and does the conversion for the communication automatically for you.
First, try to understand what is stored in the DBMS, and what you want it to store.
Maybe you need to change your DateTime type to one that considers timezones: for example: http://blogs.msdn.com/b/sqlprogrammability/archive/2008/03/18/using-time-zone-data-in-sql-server-2008.aspx
If you don't want to have timezone "adjustments" try to synchronize the DBMS session to be on the same timezone (between your client and the SQL Server) - so no conversions would occur.
There are two things you shouldn't confuse here: (1) how the data is stored in the database; (2) how it is displayed. The database should be storing the information in a timezone-agnostic way; it's up to you how you display it.
This means that there are two things that might be going wrong. Either it's being stored wrong, because the application putting things into the database is not correctly interpreting the date/time that it wants to store, or, more likely, you're converting to local time when you display it.
I'm not sure how you're doing the conversion, but lots of date/time functions will use the default locale if you don't specify one. They will allow you to specify a locale if you want to, though.
If I were you, I'd have a look at the raw data in the database to see whether that's correct.
I was wondering if there was a way to store a date (example: 01/01/2013) as datetime without SQL Server CE adding the time (example: 12:00:00 AM).
I could always store it as the string "01/01/2013" but I really want to be able to compare the dates on querying the database.
I realize that as long as I only stored the date part, all of the times in the datetime field would have equal values (i.e. 12:00:00 AM), so comparing them wouldn't be a problem and I could just always ignore the time part, however, it seems ridiculous to have this unnecessary data appended to every entry in the table.
Is there a way to store only the date part of the datetime as datetime so that the dates can still be compared in the SQL query or do I just need to live with this overhead and move on?
Side Note:
I just spent the last 30 minutes searching Google and SO for an answer I was sure was already out there, but to my surprise, I couldn't find anything on this issue.
Update:
The conclusion I have come to is that I will just accept the time in the datetime format and let it always default to 12:00:00 AM by only adding the date part during the INSERT statement (e.g. 01/01/2013). As long as the time part always remains the same throughout, the dates will still be easily comparable and I can just trim it up when I convert it to string for screen display. I believe this will be the easiest way to handle this scenario. After all, I decided to use SQL for the power of its queries, otherwise, I might have just used XML instead of a database, in the first place.
No you really can't get rid of the time component. It is part of the data type defined by sql server. I was very annoyed by it until I found that I could still display the dates without the time using JQuery to reformat them with the date formatter plugi:
https://github.com/phstc/jquery-dateFormat
Good Luck!
select CONVERT(date, GETDATE())
Here is my problem. the date that i got from my database contains "12/31/2013". Based on this date, the format is mm/dd/yy. Now the question is how do i makes it that no matter what format of the date in the user's computer, they will always read the date "12/31/2013" as mm/dd/yy instead of example dd/mm/yy which when it reads it contains an error due to there is no 31 month. i try the split method on the date i receive from my database but i coudn't get it to confirm to the format that is independent from the user's computer
Is your date being stored in your database as an actual date format, or as a string?
Remember that DateTime.Parse by default, uses the current user's current system date/time formatting settings (so UK users are dd/MM/yyyy, but US users are MM/dd/yyyy). If you want uniform parsing then use DateTime.ParseExact and specify an exact parsing format string.
One rule of thumb that's useful to remember is that "if you're ever using String.Split, you're probably doing something wrong" (I'll make exceptions for quick-and-dirty by-design programs, but for parsing a Format-string, Regular-expression, or Finite state machine is more performant (less string allocations) and less brittle.
Back on-topic, if your database is storing objects as a date or datetime then don't use strings at all. Use the .GetDateString(int) method of IDataReader or typed field properties of EF classes.
How did you get a date from your database? Did you store the date as a string? If at all possible, consider keeping the date as a DateTime variable rather than a string. If not possible, look into the DateTime.TryParse method which supports internationalization and should be able to understand with the user's UI localization settings.
Its not clear if you want to read the same format from the database or display it on the screen (UI)
If its from the sql server, consider using convert <- follow this link
I have a database with DateTime fields that are currently stored in local time. An upcoming project will require all these dates to be converted to universal time. Rather than writing a c# app to convert these times to universal time, I'd rather use available sqlserver/sql features to accurately convert these dates to universal time so I only need an update script. To be accurate, the conversion would need to account for Daylight savings time fluctuations, etc.
A User Defined Function would allow you to write an SQL query that looks like this:
SELECT toUTC([MyDateColumn], [MyTimeZoneColumn]) FROM [MyTable]
Then you get universal times back from the server without a lot of ugly syntax in the query itself. Now you could build the UDF for this with regular SQL similar to what Chris posted, but SQL Server 2005 and later will let you build the UDF using CLR (.Net: C# optional) instead. It has much better support for dates and can do a better job taking timezones and daylight savings time into account.
check out the convert function and the getutcdate function?
http://msdn.microsoft.com/en-us/library/ms187928.aspx
Check out this link from CodeProject.com - it does exactly what you want: take a date and a time zone, pass them to a UDF, and get the date in UTC or any other time zone.
IMPORTANT: Check the comments of that article - the author wasn't allowed to revise the article after a certain point, and there is an updated version of the code used for the UDFs in the comments that addresses some issues not found in the original article code.
ALSO IMPORTANT: Don't use this for querying large data sets. It's perfectly fine for a one-time load into a database, or for returning a UTC date for a single row (like a user login table or what have you.)
If you want performance, the only really acceptable method for time zone conversion is to have a lookup table that handles every possible time zone conversion for every single hour in a year, with a case statement to handle rollovers between years (ie December 31 - January 1 or vice versa.) Yes, the table is huge, but the query performance is nil.
SQL Doesn't have anything built in for this.
Two ways would be the C# application (you mentioned you don't want) or writing a really complicated update statement with something like:
UtcDate = DATEADD(hour, CASE WHEN OriginalDate BETWEEN x AND y THEN 4
WHEN OriginalDate BETWEEN x2 AND y2 THEN 5 ... END, OriginalDate)
Note - I'd recommend the C# app plus something like TZ4Net to handle the conversion.