I'm scraping a site to get the date and time a episode comes out on. So what i'm getting is Saturdays at 01:05 (JST) which is the time in japan. I have a field in my episodes table called broadcast and it has a DateTime format.
What is the best way to handle this and to change the time zone to (pst)?
Assuming you're literally scraping the string Saturdays at 01:05 (JST) off of the website, there are a few things to consider.
First, a single DateTime field is not really going to be able to represent a recurring time, like you have. Gems like IceCube were created to handle the complexities of recurring, scheduled dates. But you can get by with one DateTime field, under the assumption that it stores one instance of the broadcast and all other broadcasts are at the same time and day every week.
Now, you need to parse the string you're scraping into that date. The easiest way to do this is with the Chronic gem, which takes all sorts of English-worded time representations and turns it into a date. With your date, you need to unpluralize "Saturdays" so that Chronic knows to just find the next Saturday:
require 'chronic'
string = "Saturdays at 1:30 (JST)"
broadcast = Chronic.parse(string.sub('days', 'day'))
The broadcast variable now holds a DateTime value which you can store directly into the database. Don't worry about the time zone -- Chronic returned a Time value with zone information, so Rails will store it into your database in UTC, and convert it back out to your server timezone whenever you load it.
If you do want to convert the time to a specific zone ever, you can do so easily:
pst_time = broadcast.in_time_zone('Pacific Time (US & Canada)')
Related
I have weird situation with my PostgreSQL db date value.
On my web site I have calendar for selecting a date and when I select some future date like "2018-09-23" in PostgreSQL table column it is saved as "2018-09-22 22:00:00"?
Obviously I am missing something. On web site all the time it shows okay time "2018-09-23" but at the table it is minus one day as you see above. Why?
Rails stores DateTime fields in UTC, but without marking their time zone as UTC. This corresponds to the timestamp without time zone type in postgres. So if your time zone is +2, it'll store the time as UTC (+0).
In Rails, Time.zone will return the current local timezone (you can add logic to change this by user, for example). When persisting a datetime, Rails will automatically convert the current Time.zone to UTC. However, it doesn't use the Postgres type that actually includes the time zone data, so it relies on convention to convert back and forth to the user's time zone.
If you really only care about the date, use the date type in your migration instead of Timestamp or DateTime.
Times and dates have a lot of subtle quirks and the "right" behavior depends on your use case. In some applications, you need to deal with "local" time when considering date transitions, and sometimes you need to finesse your application or database logic to think in terms of local time and sometimes you care about UTC time.
I have table which have a datetime field named date. When doing a POST in order to insert a new row, the date sent from the client (browser) looks like 2015-11-20T14:30:00+10:00 which is actually a correct date and timezone.
However, inside Postgres this date has been inserted as 2015-11-20 04:30:00.000000, which as you can see, is not at all the same as above. I know the problem is related to the timezone. But I cannot seems to figure out a fix.
For information, I have configured my app timezone :
class Application < Rails::Application
config.time_zone = 'Brisbane'
end
Ideas?
2015-11-20T14:30:00+10:00 means that the local time of 14:30 is 10 hours ahead of UTC. Your database field reflects the correct UTC value of 04:30. This is often the desired behavior, especially if the value represent a timestamp - the date and time something occured (past tense).
In PostgreSQL, there are two different types of timestamp fields (reference)
The TIMESTAMP WITH TIME ZONE field accepts an input that contains a time zone offset. It then converts the value to UTC for storage. On retrieval, it uses the session's timezone setting.
The TIMESTAMP, or TIMESTAMP WITHOUT TIME ZONE simply stores the date and time given, ignoring any offset, and not converting to UTC.
Most of the time, you should indeed use TIMESTAMP WITH TIME ZONE. You should only use TIMESTAMP WITHOUT TIME ZONE if you need to retain the local date and time value, such as in scheduling of future events and calculation of business hours. And for those scenarios, it often makes more sense to split date and time into separate DATE and TIME fields.
One last thing - if you can avoid it, avoid using Rails time zones and use standard tzdb zones. "Australia/Brisbane" is the full tzdb identifier equivalent to the Rails "Brisbane" time zone. Refer to the section on Rails time zones at the bottom of the timezone tag wiki.
I found this gem to be incredibly useful and easy for correctly setting the time https://github.com/kbaum/browser-timezone-rails
How to convert one time zone value to another time zone value using <s:date>
For example I would like to convert
CTS to GMT+05:30(or IST) using <s:date> tag
In my database I have added date and user time zone value with respect to GMT.
my data base server is showing time zone CTS(I am unalbe to chage it).
Here I would like to convert date from CTS time zone to user time zone that is GMT+05:30(or IST) or users time zone stored in database
For Indian Standard Time, this is the way:
<s:date name = "yourDate"
format = "dd/MM/yyyy HH:mm:ss a"
timezone = "GMT+05:30" />
In the comments to this related question, you can read about common mistakes you might encounter when dealing with this.
A Date has no TimeZone. A date is just a number of milliseconds since a specific point in time (EPOCH: 01-01-1970, 00:00:00 UTC).
When you save a Date into a database, you are just saving that Long number. If your database has a specific TimeZone, it means that when you will run a query on it, it will format the Dates for human representation with that TimeZone. There are TimeZone settings in your DB, in your AS, in your framework too. But through the whole chain, the Date remains always the same Date object, just represented differently.
Many databases allows you to save the TimeZone informations along with the date. But since you said:
In my database I have added date and user time zone value with respect to GMT.
Then you can absolutely ignore the fact that
my data base server is showing time zone CTS
Just take that Date, and format it with your desired TimeZone, with the code provided.
If this is just confusing you (taking GMT dates, shown as CTS in your DB visualizer, and shown as IST in the browser), then log-print that Date three times in the Action using the three different TimeZones, to have a match between the whole chain, that will help you debugging where the conversions are applied and how.
I having an column of UNIX time stamp in my database table, which comes from a system that is in the Kuwait time zone.
My database server's time zone is Eastern Time US & Canada. Now I need to convert the UNIX time stamp in to Kuwait time zone date value using an SQL query.
Can anyone tell me how I can convert this UNIX time stamp into a Kuwait time zone date value?
Unix timestamps are integer number of seconds since Jan 1st 1970 UTC.
Assuming you mean you have an integer column in your database with this number, then the time zone of your database server is irrelevant.
First convert the timestamp to a datetime type:
SELECT DATEADD(second, yourTimeStamp, '1970-01-01')
This will be the UTC datetime that corresponds to your timestamp.
Then you need to know how to adjust this value to your target time zone. In much of the world, a single zone can have multiple offsets, due to Daylight Saving Time.
Unfortunately, SQL Server has no ability to work work time zones directly. So if you were, for example, using US Pacific time, you would have no way of knowing if you should subtract 7 hours or 8 hours. Other databases (Oracle, Postgres, MySql, etc.) have built-in ways to handle this, but alas, SQL Server does not. So if you are looking for a general purpose solution, you will need to do one of the following:
Import time zone data into a table, and maintain that table as time zone rules change. Use that table with a bunch of custom logic to resolve the offset for a particular date.
Use xp_regread to get at the Windows registry keys that contain time zone data, and again use a bunch of custom logic to resolve the offset for a particular date. Of course, xp_regread is a bad thing to do, requires certain permissions granted, and is not supported or document.
Write a SQLCLR function that uses the TimeZoneInfo class in .Net. Unfortunately, this requires an "unsafe" SQLCLR assembly, and might cause bad things to happen.
IMHO, none of these approaches are very good, and there is no good solution to doing this directly in SQL. The best solution would be to return the UTC value (either the original integer, or the datetime at UTC) to your calling application code, and do the timezone conversion there instead (with, for example, TimeZoneInfo in .Net or similar mechanisms in other platforms).
HOWEVER - you have lucked out in that Kuwait is (and always has been) in a zone that does not change for Daylight Saving Time. It has always been UTC+03:00. So you can simply add three hours and return the result:
SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01'))
But do recognize that this is not a general purpose solution that will work in any time zone.
If you wanted, you could return one of the other SQL data types, such as datetimeoffset, but this will only help you reflect that the value is three hours offset to whomever might look at it. It won't make the conversion process any different or better.
Updated Answer
I've created a project for supporting time zones in SQL Server. You can install it from here. Then you can simply convert like so:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait')
You can use any time zone from the IANA tz database, including those that use daylight saving time.
You can still use the method I showed above to convert from a unix timestamp. Putting them both together:
SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait')
Updated Again
With SQL Server 2016, there is now built-in support for time zones with the AT TIME ZONE statement. This is also available in Azure SQL Database (v12).
SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'
More examples in this announcement.
I want to store the date of an event in my database, but I want to do so without storing informations about seconds or anything smaller than seconds. Using Rails, in my migration I have the option to create a date column or a datetime column, the first one of which is too less accurate, and the second one is too much (up to the second and less). Which type should I choose to store such a date? Currently I'm using datetime and setting the seconds to a fixed value (e.g. 0) manually each time some date is set in the model.
Something like this:
self.date ||= Time.now.change(:sec => 0)
Am I totally out of track? Should I just use an integer field for each component of the date instead? (year, month, day, etc...) Or is datetime the correct type but I'm not understanding the purpose of it? (I think it's meant for timestamps and such things where seconds matter)
datetime is the correct type. And be sure to store it without time zone at time zone UTC:
http://derickrethans.nl/storing-date-time-in-database.html
At your option, use an SQL trigger to round your date to the minute on insert/update. It'll simplify your ruby code.