13 July 2015

PostgreSQL

DO NOT configure time_zone in config/application_.rb. Instead, localize_date to user timezone.

# application_helper.rb
def localize_date(date)
  I18n.l date.in_time_zone('Madrid'), format: "%d/%m/%Y %a, %H:%M" if date
end

Convert date/time strings to timestamp with to_timestamp(..)

Query:

@activities = Activity.joins(:project).select('projects.name').where("start >= to_timestamp('#{params[:start]}', 'DD/MM/YYYY')").where("start <= to_timestamp('#{params[:ended]} 23:59:59', 'DD/MM/YYYY HH24:MI:SS')").group(:name).sum(:duration)

@number_of_entries = Activity.where("start >= to_timestamp('#{params[:start]}', 'DD/MM/YYYY')").where("start <= to_timestamp('#{params[:ended]} 23:59:59','DD/MM/YYYY HH24:MI:SS')").count

@total_duration = Activity.where("start >= to_timestamp('#{params[:start]}', 'DD/MM/YYYY')").where("start <= to_timestamp('#{params[:ended]} 23:59:59', 'DD/MM/YYYY HH24:MI:SS')").sum('duration')

Attention: Rails time zone <= vs => PG UTC

PostgreSQL save Ruby DateTime into timestamp UTC (WITHOUT timezone)

Function to_timestamp(date-time , format ) converts string date-time into timestamp WITH timezone, ie UTC+1 / UTC+2 summer

Working with time zone recommendations

http://www.elabs.se/blog/36-working-with-time-zones-in-ruby-on-rails

Configure: config.time_zone in config/application.rb

  • Use: Time.zone.parse
  • Use: 2.hours.ago
  • Preferred Time (or DateTime) to Date because the former includes date info. Date doesn't include time info.
  • Use: Date.today.in_time_zone. Never Date.today.to_time
  • Quering with rails way (never SQL). Ex: Post.where([“posts.published_at > ?”, Time.current])

Cheat Sheet

DOs

2.hours.ago # => Fri, 02 Mar 2012 20:04:47 JST +09:00
1.day.from_now # => Fri, 03 Mar 2012 22:04:47 JST +09:00
Date.today.in_time_zone # => Fri, 02 Mar 2012 22:04:47 JST +09:00
Date.current # => Fri, 02 Mar
Time.zone.parse("2012-03-02 16:05:37") # => Fri, 02 Mar 2012 16:05:37 JST +09:00
Time.zone.now # => Fri, 02 Mar 2012 22:04:47 JST +09:00
Time.current # Same thing but shorter. (Thank you Lukas Sarnacki pointing this out.)
Time.zone.today # If you really can't have a Time or DateTime for some reason
Time.current.utc.iso8601 # When supliyng an API (you can actually skip .zone here, but I find it better to always use it, than miss it when it's needed)
Time.strptime(time_string, "%Y-%m-%dT%H:%M:%S%z").in_time_zone # If you can't use time.zone.parse

DON'Ts

Time.now # => Returns system time and ignores your configured time zone.
Time.parse("2012-03-02 16:05:37") # => Will assume time string given is in the system's time zone.
Time.strptime(time_string, "%Y-%m-%dT%H:%M:%S%z") # Same problem as with Time#parse.
Date.today # This could be yesterday or tomorrow depending on the machine's time zone.
Date.today.to_time # => # Still not the configured time zone.

Work with Time.zone

http://danilenko.org/2012/7/6/rails_timezones/

Server in UTC+4 Client in UTC-5

Time.zone = 'EST'
DateTime.now.to_s
# => "2012-07-06T13:30:00+04:00"
Time.now.to_s
# => "2012-07-06 13:30:00 +0400"
Time.zone.now.to_s
# => "2012-07-06 04:30:00 -0500"
Time.zone = 'EST'
Time.now.end_of_day.to_s
# => "2012-07-06 23:59:59 +0400"   >><<<<>><< WRONG!!!
Time.zone.now.end_of_day.to_s
# => "2012-07-06 23:59:59 -0500"   >><<<<>><< GOOD!!!

GOOD

Time.zone = 'EST'
Time.now.in_time_zone.end_of_day.to_s
# => "2012-07-06 23:59:59 -0500"
Time.zone.now.end_of_day.to_s
# => "2012-07-06 23:59:59 -0500"

Cheat sheet

Get current time

Time.zone.now
Time.current

Get Day (Today, Yesterday, etc.)

Time.zone.today
Time.zone.today - 1

Build time

Time.zone.local(2012, 6, 10, 12, 00)

Time From Timestamp

Time.zone.at(timestamp)

Parse Time (Simple)

Time.zone.parse(str)

Parse time with explicit format

Time.zone.parse(str, "%Y-%m-%d %H:%M %Z").in_time_zone    #<<<<<< acceptable
Time.zone.strptime(str, "%Y-%m-%d %H:%M")        # <<<< better with gem time_zone_ext [[https://github.com/doz/time_zone_ext]]

Getting time for date

date.beggining_of_day

Testing dates in timezone with postgres

# factory.rb
activation_date { Time.current.utc.iso8601 }