https://en.wikipedia.org/wiki/ISO_8601 ISO 8601 describes representation of dates and times as an international standard
Time zones in ISO 8601 are represented as local time (with the location unspecified), as UTC, or as an offset from UTC.
The Z suffix in the ISO 8601 time representation is sometimes referred to as "Zulu time" because the same letter is used to designate the Zulu time zone. "14:45:15Z"
Where is Zulu ? in South Africa.
Let's be coordinated in this world 🌎 🌍 🌏. UTC is the offest from the Zulu time, the Greenwich Mean Time (GMT).
"−05:00" for New York on standard time (UTC-05:00)
"−04:00" for New York on daylight saving time (UTC-04:00)
"+00:00" (but not "-00:00") for London (UTC±00:00)
"+02:00" for Cairo (UTC+02:00) or paris :yellow_heart:
"+05:30" for Mumbai (UTC+05:30)
"+14:00" for Kiribati (UTC+14:00)
Paris (UTC+02:00)
All the list from wikipedia : List of UTC time offsets https://en.wikipedia.org/wiki/List_of_UTC_time_offsets
By default the date are stored in UTC. So you are in Zulu time. Why ? conveniant for worldwide application. But it can be changed with this kind of configuration :
config.time_zone = 'Eastern Time (US & Canada)'
New york has a "−05:00" UTC offset. So the time is configured as -5 hours.
Note bellow the +0 this server is configured as UTC. It's 22h in France. So 22h with 2 hours offset.
irb(main):019:0> Time.now
=> 2020-06-24 20:21:56.2667183 +0000
%T
: to display the time
%T %z
: to display the UTC offset (the difference with the Zulu time.)
irb(main):020:0> Time.now.strftime("%T")
=> "20:23:16"
irb(main):021:0> Time.now
=> 2020-06-24 20:23:18.3238636 +0000
irb(main):022:0> Time.now.strftime("%T %z")
=> "20:23:27 +0000"
When was created the album ?
irb(main):003:0> album.created_at
=> 2020-06-24 11:00:05 -0500
What we should do to display on a different timezone, for exemple in Paris ? --> the same if we had stored the date in UTC.
irb(main):004:0> album.created_at.in_time_zone("Europe/Paris")
=> Wed, 24 Jun 2020 18:00:05 CEST +02:00`
CEST ? Central European Summer Time (CEST) is 2 hours ahead of Coordinated Universal Time (UTC). This time zone is a Daylight Saving Time time zone and is used in: Europe, Antarctica.
This time zone is often called Central European Summer Time.
If you do not take the UTC offset into consideration. For exemple, let's be in NY and share the time :
irb(main):007:0> album.created_at.strftime("%T")
=> "11:00:05"
irb(main):008:0> album.created_at
=> 2020-06-24 11:00:05 -0500
On the first line we lost the time offset with our friend Zulu. On the second we know the time coordinated with the world.
What's the answer ?
(1) Use ISO 8601 and add the UTC
(2) If you do not want to have the Zulu time and say on which timezone you want to be
irb(main):003:0> album.created_at
=> 2020-06-24 11:00:05 -0500
irb(main):004:0> album.created_at.in_time_zone("Europe/Paris")
=> Wed, 24 Jun 2020 18:00:05 CEST +02:00
https://github.com/ruby/ruby/blob/995923b7f9178c234f8c685f434407eb4f0eeb5c/ext/date/date_core.c#L249
struct SimpleDateData
{
unsigned flags;
int jd; /* as utc */
VALUE nth; /* not always canonicalized */
date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
/* decoded as utc=local */
int year; /* truncated */
#ifndef USE_PACK
int mon;
int mday;
/* hour is zero */
/* min is zero */
/* sec is zero */
#else
/* packed civil */
unsigned pc;
#endif
};
struct ComplexDateData
{
unsigned flags;
int jd; /* as utc */
VALUE nth; /* not always canonicalized */
date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
/* decoded as local */
int year; /* truncated */
#ifndef USE_PACK
int mon;
int mday;
int hour;
int min;
int sec;
#else
/* packed civil */
unsigned pc;
#endif
int df; /* as utc, in secs */
int of; /* in secs */
VALUE sf; /* in nano secs */
};
union DateData {
unsigned flags;
struct SimpleDateData s;
struct ComplexDateData c;
};
Note that USE_PACK is defined line 22. https://github.com/ruby/ruby/blob/995923b7f9178c234f8c685f434407eb4f0eeb5c/ext/date/date_core.c#L22
the integer of is the offset. Used in df_local_to_utc
coppied bellow for exemple.
https://github.com/ruby/ruby/blob/995923b7f9178c234f8c685f434407eb4f0eeb5c/ext/date/date_core.c#L882
inline static int
df_local_to_utc(int df, int of)
{
df -= of;
if (df < 0)
df += DAY_IN_SECONDS;
else if (df >= DAY_IN_SECONDS)
df -= DAY_IN_SECONDS;
return df;
}
irb(main):010:0> Time.zone
=> #<ActiveSupport::TimeZone:0x00005595e9818948 @name="UTC", @utc_offset=nil, @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>>
irb(main):011:0> Time.zone = 'Europe/Paris'
irb(main):012:0> Time.zone.now
=> Wed, 24 Jun 2020 21:55:07 CEST +02:00
irb(main):013:0> Time.now
=> 2020-06-24 19:55:18.8506586 +0000
irb(main):014:0> Time.zone
=> #<ActiveSupport::TimeZone:0x00005595e97cc8e0 @name="Europe/Paris", @utc_offset=nil, @tzinfo=#<TZInfo::DataTimezone: Europe/Paris>>
thoughtbot : https://thoughtbot.com/blog/its-about-time-zones