Ion DateTime also sends DateTime as UTC (Z) - ruby-on-rails

My Ionic 3 app uses the ion DateTime field where the user inputs a date.
<ion-datetime displayFormat="DD/MM/YYYY HH:mm" [(ngModel)]="scheduled_at"></ion-datetime>
This gets then send to my Rails 5 API. The string that arrives at my API endpoint looks like this:
"scheduled_at"=>"2018-06-14T23:33:42.939Z"
I read that the Z indicates UTC (https://robots.thoughtbot.com/its-about-time-zones). The issue is that the timezone the user enters is not in ZTC but in 'America/Sao_Paulo', so when I parse the string to a DateTime object in Rails and store it to the DB it will always be wrong.
Is there any way to tell the ion DateTime the correct timezone?

Maybe, there is no way to do that. moment.js is an alternative.
In ionic datatime documentation,
Advanced Datetime Validation and Manipulation
The datetime picker provides the simplicity of selecting an exact
format, and persists the datetime values as a string using the
standardized ISO 8601 datetime format. However, it's important to note
that ion-datetime does not attempt to solve all situtations when
validating and manipulating datetime values. If datetime values need
to be parsed from a certain format, or manipulated (such as adding 5
days to a date, subtracting 30 minutes, etc.), or even formatting data
to a specific locale, then we highly recommend using moment.js to
"Parse, validate, manipulate, and display dates in JavaScript".
Moment.js has quickly become our goto standard when dealing with
datetimes within JavaScript, but Ionic does not prepackage this
dependency since most apps will not require it, and its locale
configuration should be decided by the end-developer.

Try to use toLocaleString() string function of Date
myDate: String = new Date().toLocaleString();

Related

Rails app datetime search using Ransack gem

I was about to implement a search function where users can filter a datetime column.
I am currently using rails datetime_field_tag however I can't seem to make it work with ransack where people can choose a date with time in hours and minutes then either AM or PM.
Users can enter datetime in this format: dd/mm/yyyy hh:mm AM/PM
The column that i am searching for is in datetime format, ex: 2021-05-12 09:09:48
What's the best way to implement this one? with ransack or not? and how?
just my first time implementing datetime search function with ransack,
I tried searching online but i cant seem to find a good solution.
thanks.
If you're receiving the datetime in string format from parameters and directly passing it to ransack, then you should convert that string to 24-hour format string (db format can also be used) first and then pass it to ransack.
For example
query_value = Time.zone.parse(params[:created_at_filter]).to_s(:db)
Person.ransack(created_at_eq: query_value)

Rails column type for moment.js formatted date and time

I am building a rails app, where the user picks up a date from a date picker and a time from the time picker. Both the date and time have been formatted using moment js to show the date and time in the following way:
moment().format('LL'); //January 23,2017
moment().format('LTS'); //1:17:54 PM
I read this answer with guidelines about selection of a proper column type.
Is there documentation for the Rails column types?
Ideally, I should be using :date, :time or :timestamp for this. But since the dates are formatted, should I be using :string instead?
Which would be the correct and appropriate column type to use in this situation?
If you want to store a time reference in your database you should use one of the types the database offers you. I'll explain this using MySQL (which is the one I have used the most) but the explanation should be similar in other database servers.
If you use a timestamp column you will be using just 4 bytes of storage, which is always a good new since it makes smaller indexes, uses less memory in temporal tables during the internal database operations and so on. However, timestamp has a smaller range than datetime so you will only be able to store values from year 1970 up to year 2038 more or less
If you use datetime you will be able to store a wider range (from year 1001 to year 9999) with the same precision (second). The bad consequence is that a higher range needs more memory, making it a bit slower.
There are some other differences between these two column types that don't fit in this answer, but you should keep an eye on before deciding.
If you use varchar, which is the default column type for text attributes in Ruby on Rails, you will be forced to convert from text to datetime and vice-versa every time you need to use that field. In addition, ordering or filtering on that column will be very inefficient because the database will need to convert all strings into dates before filtering or sorting, making it impossible to use indexes on that column.
If you need sub-second precision, you can use bigint to meet your requirements, as MySQL does not provide a date specific type for this purpose
In general, I recommend using timestamp if your application requirements fit the timestamp limitation. Otherwise, use datetime, but I strongly discourage you to use varchar for this purpose.
EDIT: Formatting
The way you store dates in database is completely different from the way you display it to the user. You can create a DateTime object using DateTime.new(year, month, day, hour, minute, second) and assign that object to your model. By the time you save it into database, ActiveRecord will be in charge of converting the DateTime object into the appropiate database format.
In order to display a value that is already stored in database in a specific format (in a view, API response, etc.) you can hava a look at other posts like this one.
You can have a timestamp column in your database, and then parse the request to a ruby datetime object like this:
d = Time.parse(params[:date])
t = Time.new(params[:time])
dt = DateTime.new(d.year, d.month, d.day, t.hour, t.min, t.sec, t.zone)
#now simply use dt to your datetime column
On Postgres you can save a ruby DateTime object straight into a postgres timestamp field, e.g
User.first.update_attribute('updated_at', dt )
Another option is to concatenate your date and time strings into one and then u can do a one-liner:
User.last.update_attribute('created_at', Time.parse('January 23,2017 1:17:54 PM'))
I'm pretty sure this will work on MySQL datetime or timestamp as well.
Credit to david grayson Ruby: combine Date and Time objects into a DateTime

Dygraphs timestamp with timezone

I know there was a lot of discussion about datetime parsing in dygraphs and problems with Javascript. But still, I have a problem how to correctly pass datetime.
I'm using dygraph to show data (points with 5 seconds interval) and it's crucial to have correct datetime. But if I pass datetime as timestamp (1401580800) or as ISO 8601 (2014-06-01T00:00:00+00:00), I always get datetime modified to my local time.
My question is, how to correctly pass the datetime to dygraph so datetime doesn't change?
Dygraphs use Javascript Dates, which display according to your local timezone (unfortunately, there's no way to display them using an arbitrary timezone).
One solution is to modify the data - I've encountered a similar problem in my own work, and I made a small helper function to make fake Javascript UTC dates (basically ending up with a Javascript date that's actually the wrong time but shows up looking correct when displayed in local time). This worked for my application, which used moments (http://momentjs.com/) to represent dates everywhere unless required by some other library to use Javascript's Dates.
Another (probably more correct) solution is to modify Dygraph's functions to display the right things, as demonstrated in the answer to this post: Dygraph showing dates in an arbitrary Timezone
The JavaScript Date object will always use the local time of the computer it's running on. If you don't want that behavior, you'll need to use something else. Consider building a pre-formatted string using something like moment.js and then just pass the string to dygraphs instead of the date.

Adding drupal node containing date in drupal-ios-sdk

I am developing an iOS app that needs to create drupal nodes. I am using drupal-ios-sdk to create the nodes. It works fine sending strings to text fields in drupal but the node also needs to contain a date field. When I convert and format the NSDate to a string and put it in a dictionary and send like a text field I get an error from the drupal services module indicating that the date is in the wrong format. What is the correct format or where would I find some documentation?
Here is the best way to find it.
Create a node on your Drupal site first and check the database column for your date field. Then send the date value in the date value in the same format. Also, if you are using date module -- that's obvious, you can convert the string using some date function from the date module.

TIme.now and Created_At different formats?

Ive noticed that in a model the created_at attribute when rendering a model to json has the format like:
2013-05-20T22:12:31Z
and calling Time.now and rendering to json gives a format like:
2013-05-21 00:04:03 +0000
I am trying to create a web service for an iOS app where I need to compare the current time vs the created time but cant do so because of the timezone difference.
What does the Z in the Created_at attribute represent? Is that a timezone? If so how do I change the Time.now timezone to match?
If Z is not a timezone, any recommendations?
ActiveRecord Timestamp columns (like created_at and updated_at) are loaded as the type ActiveSupport::TimeWithZone, while Time.now produces a Time. These classes have different default to_s formats, which accounts for your discrepancy.
As you guessed, both the Z and the +0000 relate to the timezone of the datetime. Your created at value is being expressed as an ISO 8601 date where Z means Zulu, another way of expressing the UTC or GMT 0-offset timezone. Good news is that means both of your dates are already in UTC.
I'm not sure what your use case is, but you should consider doing this date comparison on the server if possible instead of in the iOS client. In that case the string representation wouldn't matter since the underlying numerical values of the dates would be compared.
If you really need to do the comparison on the iOS client, then you need to explicitly format both date values when rendering the JSON so you will have a consistent representation. You'll want to do a created.strftime(...) and Time.now.strftime(...) to format the values. ISO 8601 is a good choice for date formats in an API, although you will probably want to check and see what's easiest to consume given the iOS libraries you are using.

Resources