Carbon::now() with time-offset result in different behaviors - laravel-5.1

I'am using Carbon for manipulating dates in a laravel project.
Carbon::now('+5:30');
Above code is working fine in local environment but not in development environment.
This is what i get on dd(Carbon::now('+5:30'));
1 - IN LOCAL ENVIRONMENT php version - 5.6.3
2 - IN DEVELOPMENT ENVIRONMENT php version - 5.5.9-1ubuntu4.14
But both environment behaves same if i use timezone name instead of time-offset like,
Carbon::now('Asia/Tokyo');
Is this something about the php-version or something else?

I have an answer for you after searching for related issues.
It seems that PHP version 5.5.9 had a bug:
https://stackoverflow.com/a/14069062/5912664
So you can't use that method with Carbon, but the following should work:
Carbon::now()->addHours(5)->addMinutes(30);
You can place your servers timezone in there for added accuracy:
Carbon::now(date_default_timezone_get())->addHours(5)->addMinutes(30);

you can change in
'timezone' => 'UTC'
This time zone must match to your country zone.So replace this UTC with your current zone.

Related

How does Rails know my timezone?

How does Rails know my time zone? I don't have it set in application.rb:
# config.time_zone = 'Central Time (US & Canada)'
I searched the whole app for time_zone and that is the only instance of it. I don't see any environment variables for time zone set either. I'm on Windows.
C:\Users\Chloe\workspace\MyBestBody>rails runner "p Time.now"
DL is deprecated, please use Fiddle
2015-06-12 23:38:33 -0400
It prints UTC time when deployed to Heroku.
C:\Users\Chloe\workspace\MyBestBody>heroku run rails console
Running `rails console` attached to terminal... up, run.1949
Loading production environment (Rails 4.2.1)
irb(main):001:0> Time.new
=> 2015-06-13 03:28:34 +0000
Rails 4.2.1
From gettimeofday(), or so the ruby MRI source would have me believe:
int __cdecl
gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
filetime_to_timeval(&ft, tv);
return 0;
}
Per comment, this is a C function, called by the ruby date routines under the hood. You do not call the method yourself, rather you call the ruby methods you are calling.
Your question involves two separate things.
The first is what ruby thinks the time zone is. This is the zone used when you use things likeTime.now or Time.mktime. Ruby uses the C level APIs provided by the operating system to get this information (the TZ environment variable can override this on unixy operating systems).
The second is the time zone your users will see when they use your app. This is frequently not the same thing. Even if your users were all in the same timezone it's a good idea to have your servers use UTC because it is free from things like daylight savings time.
For this reason rails has its own timezone system and the setting you found controls the default value of that timezone. Sometimes you might overwrite this on a per user basis. Rails always records information in UTC, but it will be displayed in views using the value of Time.zone (And input from forms is interpreted in that zone). You can see what the current time in this zone is by doing
Time.zone.now

Rails 4: Using ActionView helpers in model works in development env but not in production

I use the following code in one of my models
def jasper_amount
ActionController::Base.helpers.number_to_currency(amount)
end
I know that it breaks MVC. However, in this case it is the best solution. I have to pass data to Jasper via the Ruby Java Bridge and formatting in Jasper would be much more complicated.
Calling object.jasper_amount from the rails console works fine and prints the expected results. This works fine in development and production.
Now, to pass the data to Jasper I first have to create an xml version of the object's attributes using object.to_xml(methods: [:jasper_amount]).to_s This works in development but not in production. In production the value for jasper_amount that is passed to Jasper is "0.00 €". However, if I remove number_to_currency from def jasper_amount (just returning unformatted amount) it works. What's even more confusing is the fact that calling jasper_amount from the rails console in productions works. I guess the culprit must be to_xml, but I have no idea why it works in development and not in production.
The problem was with Ruby Java Bridge (rjb) and BigDecimal. If you use BigDecimal with rjb, you have to include the "BigDecimal" gem in your Gemfile. Otherwise all your BigDecimals will be 0 (and that all over your app!)

Define "current time" when starting Rails?

I have an app that changes behavior based on the time of the day, and I'd like to be able to just spin up the server and test how it works at different times.
Ideally, I'd like to be able to just pass in the time as an argument when I run rails s, like rails s TIME=2014-02-26 22:06:11 -0500.
In config/locales/application.rb you can set the timezone before running rails s.
config.time_zone = 'Alaska'
If you're running OS X, you can also set the system time in the terminal before running rails s.
date 022611002013
The format is [month][day][hh][mm][year], so the above is 11:00 February 26, 2013. You can change your system time back to the current time in the terminal or Date and Time preferences panel.
You can actually read environment variables from within rails (actually Ruby). This is how to do it:
require 'date'
$startup_time = DateTime.parse(ENV['STARTUP_TIME']) rescue DateTime.now
puts "Server started at: #{$startup_time}"
You'd call this code placed in pull_time.rb like this:
STARTUP_TIME="2014-02-26 22:06:11 -0500" ruby pull_time.rb
In order to have this global variable work in Rails, you want to add it to an initializer.
So put the code above in config/initializers/set_startup_time.rb
You can now access $startup_time anywhere in your code. Just pass STARTUP_TIME as an environment variable to rails.
STARTUP_TIME=2014-02-26 22:06:11 -0500 rails s
Rails server uses time of the hosting machine. So if you are running on local machine then changing the time of the local operating system will also have effect on your rails server
If it's hosted on another server then you have to change that server's time.
Don't try changing the time of your server. That can play real havoc with cron jobs or other time-based services.
Instead, have you tried defining the starting time as a specific value in your code then running the server? Then set it to the next time you need, and run the server again?
Time.new(2013, 12, 31, 12, 59, 59) # => 2013-12-31 12:59:59 -0700
You could also use the time as an integer, using the number of seconds that represent the time you want the server to think it is. Pass that in as an ENV hash element, then check to see if it's defined. If it is, define the time based on that value, otherwise don't define the ENV value and the server will run as normal:
ENV['SERVER_TIME'] = '1388519999'
server_time = ENV['SERVER_TIME'] ? Time.at(ENV['SERVER_TIME'].to_i) : Time.now
server_time # => 2013-12-31 12:59:59 -0700
Then, when you need to test the server, you could write a little shell script that sets that value and runs rails s, test the server then quit it, and rerun the shell script with a different value.
You can change Rails' internal timezone by adding config.time_zone = 'Pacific' to application.rb.
If you're deploying to Heroku, you can do the same slightly differently: heroku config:add TZ="Europe/Athens".
However, the downside is that neither of these commands allows you to define a specific time for the app (just the timezone, so you get the current time in another timezone), nor can you run these from command-line when starting your local Rails server.
Rails server determine time from the hosting machine
So changing the system's time would do the trick
EDIT:
As 'sevenseacat' said in comment
you can also use gem timecop to test your application without changing system's time.

Rails Postgres Time Zone Handling

The simple thing I want is to store a DateTime in UTC in the database and retrieve it in UTC again, but rails seems to assume I stored the DateTime in my local time zone and adds the 8 hours difference (PST). I have a DateTime field in my model. If I send a request (PUT) to update this field in a particular instance of my model, somehow timezones get mixed up for whatever reason:
Sending to rails via PUT: 2012-02-17T03:46:58Z
Returned via subsequent GET: 2012-02-17T11:46:58Z
The time difference is exactly 8 hours and could be explained by my timezone which is PST (-08:00).
I am using Datamapper 1.2 on Rails 3.1.3.
I set my application config timezone to UTC explicitly.
I also tried to use dm-zone-types. Did not change anything for me.
A git-bisect on my repo revealed, that this misbehavior was introduced as I switched the database to postgres from the original sqlite. This commit only changed the database.yml and the gemfile. Nothing else.
Any ideas?
I have found a hacky solution myself:
Set the servers timezone in the environment variable TZ to 'UTC'. In order to persist this configuration option, I decided to put the environment variable setting in config/boot.rb:
ENV['TZ'] = "UTC"
I still feel dirty and this solution still gives me the willies. So any better/cleaner solution is highly appreciated!

How do I format datetime values to more friendly formats?

I'm fairly new to Ruby on Rails. I created a blog using SQLite3, because I am unable to install MySQL, and would like to display the date of creation next to the title.
The date of creation is created using a timestamp. As I am new to RoR I created the blog using generate scaffold so I'm not 100% sure how that all works.
At the moment, when I display the created_at field, I'm given an ugly format:
2011-12-05 14:11:10 UTC
Is there a way to change this so that it display DD-MM-YYYY HH:MM, or preferably to say "posted 30 days ago". I realize the latter would be a lot more tricky.
I think you're looking for strftime - ruby documentation here.
Example:
irb(main):001:0> a = Time.now
irb(main):002:0> a.strftime("%d-%m-%Y %H:%M")
=> "05-12-2011 15:08"
First of all: you will have to install something other than SQLite (I recommend PostgreSQL, not MySQL). SQLite is unsuitable for production, and you don't really want your dev and production DB servers to be different.
To your question: Ruby and Rails have lots of date formatting methods. to_s might do what you want, or there's things like ActionView::Helpers::DateHelper.time_ago_in_words.

Resources