How to deal with the time zone difference - mysql

Using mysql, in a post table I use CURRENT_TIMESTAMP to store the date_time of publication.
Everything was ok when I was working on wampserver on local.
But I hosted my site yesterday on a server located in France, 2 hours away from the time zone of my country.
I'm using a timeago plug-in which processes the date and displays the elapsed time (there is .. sec ago, there is .. min ago, there is .. h ago, there is .. year ago) since the publication of a content.
After posting, I see "2 hours ago" when I just published 30 seconds ago.
How can I take into account the time zone of my users compared to the date and time of the server of my host?
Sample: If I post a content, 30 seconds later Me and the user who is at china or anywhere must see "30 seconds ago".
I tried that:
$d ="2020-02-28T13:09:33Z";
<time class='timeago' datetime='<?= $d ?>'> </time>
But instead of giving me "30 seconds ago", It gives me "2 hours ago".
Thank you.

I suspect you are calculating the relative time on the client side. For example, by timego plugin.
Neither MySQL, nor PHP know user's location and timezone. So, it's better to inform JS about server timezone and let it calculate the offset right.
Use ISO 8601 date time format to let timeago pligin know about server timezone. All the rest is up to JS plugin:
<?php
$ts = strtotime($row['date_time']);
?>
<time class="timeago" datetime="<?= date(DATE_ISO8601, $ts) ?>">
<?= date('Y-m-d H:i:s', $ts) ?>
</time>
<script type="text/javascript">
jQuery(function($) {
$("time.DateTime").timeago();
});
</script>

MySQL stores DATETIME without timezone information, but datetime values that are not timezone-aware are semi-useless.
So you have different options.
First option: continue to store datetime values in your current timezone, but add a second column with the proper 'offset' versus UTC, for example +1 if you are in France. Then you can perform calculation on the fly to another timezone but it is tricky because of daylight saving settings. During a certain period of the year the offset will be +1, at other times it could be +2.
So I don't recommend this approach. It's not going to scale well over time.
Other option: you can store all datetime values as UTC in your database and
then in your application you recalculate them by applying the correct offset according to your own timezone (or that of your web visitors).
This is a better option.
Whatever you do, it is important to know the timezone that applies to a given datetime value. So choose one and stick to it.
PHP has functions to handle time zone conversions, see for example: https://www.php.net/manual/en/class.datetimezone.php
Note that TIMESTAMP is limited to 1970-2038... Year 2038 problem

Related

Timezone conversion in a Google spreadsheet

I know this looks simple.
In a Google spreadsheet, I have a column where I enter time in one timezone (GMT)
And another column should automatically get time in another time zone(Pacific Time)
GMT | PT
----------|------------
5:00 AM | 9:00 PM
As of now I am using
=$C$3-time(8,0,0)
The problem here is, I want to change the time formula for Daylight savings.
Is there any function or script available which can take the daylight saving into calculation automatically.
Short answer
There is no built-in function but you could build a custom function.
Example
/**
* Converts a datetime string to a datetime string in a targe timezone.
*
*#param {"October 29, 2016 1:00 PM CDT"} datetimeString Date, time and timezone.
*#param {"Timezone"} timeZone Target timezone
*#param {"YYYY-MM-dd hh:mm a z"} Datetime format
*#customfunction
*/
function formatDate(datetimeString,timeZone,format) {
var moment = new Date(datetimeString);
if(moment instanceof Date && !isNaN(moment)){
return Utilities.formatDate(moment, timeZone, format)
} else {
throw 'datetimeString can not be parsed as a JavaScript Date object'
}
}
NOTE:
new Date(string) / Date.parse(string) implementation in Google Apps Script doesn't support some timezones abbreviations.
From https://tc39.es/ecma262/#sec-date-time-string-format
There exists no international standard that specifies abbreviations for civil time zones like CET, EST, etc. and sometimes the same abbreviation is even used for two very different time zones.
Related
Get UTC offset from timezone abbreviations
Explanation
In order to consider daylight saving time zones the input argument for of the value to be converted should include the date, no only the time of the day. You could set a default date and time zone to build the datetimeString by concatenating it before calling the formula.
=formatDate("October 29, 2016 "&A2&" GMT","PDT","hh:mm a")
For the target timezone besides the three letter abbreviation we could use TZ database names like America/Los_Angeles, example:
=formatDate("October 29, 2016 "&A2&" GMT","America/Los_Angeles","HH:mm")
If timezone abbreviation and TZ name fails for the datetimeString use time offsets (i.e. UTC-4).
See also
Calculating year, month, days between dates in google apps script
References
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date
This tutorial was amazingly helpful: https://davidkeen.com/blog/2017/01/time-zone-conversion-in-google-sheets/
Google Sheets does not have a built in way of converting time zone data but by using the power of Moment.js and Google’s script editor we can add time zone functionality to any sheet.
These are the files I copied into my script project:
https://momentjs.com/downloads/moment-with-locales.js saved as moment.js
https://momentjs.com/downloads/moment-timezone-with-data.js saved as moment-timezone.js
Make sure you add the moment.js script first and have it above the moment-timezone.js script because moment-timezone.js depends on it.
Then in your other script project, your Code.gs file can look like this:
var DT_FORMAT = 'YYYY-MM-DD HH:mm:ss';
/**
https://stackoverflow.com/questions/34946815/timezone-conversion-in-a-google-spreadsheet/40324587
*/
function toUtc(dateTime, timeZone) {
var from = m.moment.tz(dateTime, DT_FORMAT, timeZone);//https://momentjs.com/timezone/docs/#/using-timezones/parsing-in-zone/
return from.utc().format(DT_FORMAT);
}
/**
https://stackoverflow.com/questions/34946815/timezone-conversion-in-a-google-spreadsheet/40324587
*/
function fromUtc(dateTime, timeZone) {
var from = m.moment.utc(dateTime, DT_FORMAT);//https://momentjs.com/timezone/docs/#/using-timezones/parsing-in-zone/
return from.tz(timeZone).format(DT_FORMAT);
}
The easiest method is using a simple calculation.
Use =NOW() command in sheets and subtract it with the time difference divided by 24.
Example:
IST to Colombia
=NOW()-(10.5/24)
The time difference from India to Colombia is 10hours and 50min, we need to subtract it from the "Now" time and divide it by 24.
If the time zone is ahead of your place, then you need to add it.
Example:
IST to JAPAN:
=NOW()+(3.5/24)
=Now is set to US time by default, you can change it under general in settings.
enter image description here
enter image description here
I had the same problem (convert Manila Time to Sydney Time and automatically adjust for daylight saving time) when I found this page.
I didn't want to have a custom function but I found that, in Sydney, AEST (Australian Eastern Standard Time) starts on the first Sunday of April and AEDT (Australian Eastern Daylight Time) starts on the first Sunday of October.
So I thought, if I could find a formula that detects whether a date falls between the first Sunday of April and first Sunday of October (Standard Time) then I can automatically add 1 hour to the usual 2 hours to Manila time during Daylight Saving Time (dates falling outside the two dates) to have Sydney Time.
These two Excel solutions worked fine in Google Sheets:
How You Can Determine the First Sunday in a Month in Excel
How to determine if a date falls between two dates or on weekend in Excel
First Sunday of April this year (A1):
=CONCATENATE("4/1/",Year(today()))+CHOOSE(WEEKDAY(CONCATENATE("4/1/",Year(today())),1),7,6,5,4,3,2,1)
First Sunday of October this year (A2):
=CONCATENATE("10/1/",year(today()))+CHOOSE(WEEKDAY(CONCATENATE("10/1/",year(today())),1),7,6,5,4,3,2,1)
DST detector (A3) — if a date falls outside these two dates, it's DST in Sydney:
=IF(AND(today()>A1,today()<A2),"AEST","AEDT")
Time in Sydney (A4):
=NOW()+TIME(IF(A3="AEDT",3,2),0,0)
NOW() can be changed to any time format for tabulation:
I'm a new contributor and a novice, but I stumbled upon a function that had not been mentioned despite many hours of searching on the Sheets/Time Zone issue. Hoping this relatively simple solution will help.
For my sheet, I just want to add a row and automatically populate the local sheet date and time in the first two cells.
The .getTimezoneOffset() returns the difference in minutes between the client TZ and GMT, which in NY during Daylight Savings Time is 240. The function returns a positive number for the zones with "GMT-x", and vice versa for zones with "GMT+x". Hence the need to divide by -60 to get the correct hour and sign.
function addRow() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
sheet.insertRows(2, 1);
rightNow = new Date();
var tzOffset = "GMT" + rightNow.getTimezoneOffset() / -60;
var fDate = Utilities.formatDate(rightNow, tzOffset, "MM-dd-yyyy");
var fTime = Utilities.formatDate(rightNow, tzOffset, "HH:mm");
sheet.getRange('A2').setValue(fDate);
sheet.getRange('B2').setValue(fTime);
sheet.getRange('C2').setValue(tzOffset);
}
I've since found that I'm not the first person to respond to the GMT correction connundrum mentioning .getTimezoneOffset(). However, this thread has the most views on this topic, so I figured this option deserves a mention.
DST ends here on November 7th, 2021, so I'll report back if it doesn't adjust as expected to "GMT-5"
.getTimezoneOffset()
That can also be done without macros. Just using functions and data manipulation will suffice. Explaning the whole process here would be a bit cumbersome. Just do your research on how the various time functions work and use your creativity.
Hint: Use =NOW() if you want both current date and time. You'll actually need that if you need to find out the precise diff in time between to different dates.
Use =NOW()-INT(NOW()) when you only want the time (with date truncated if both times fall on the same date). Then format the corresponding cell or cells for time (i.e. 4:30 PM), not for date-time (3/25/2019 17:00:00). The latter is the format you'd use when you want to show both date and time... like when you use NOW().
Also search online for the Daylight Saving Time offset for the various standard time zones (PT, MT, CT, ET, AT) with respect to the Coordinated Universal Time (UTC). For example, in 2019 the offset for Pacific Time is UTC-7 when DST is observed starting on March 10 at 2 AM (Pacific) until November 3 at 2 AM. That means that the difference in time from UTC to Pacific is 7 hours. During the rest of the year is 8 hours (UTC-8). During DST observance starting sometime in March (the 10th this yr) it goes from PST to PDT by moving clocks forward 1 hr, or what we know as UTC-7 (that's summer time). After DST observance it goes from PDT to PST by moving clocks back 1 hr again, or what we know as UTC-8 (or winter time). Remember that the clock is advanced one hour in March to make better use of time. That's what we call DST, or Daylight Saving Time. So after March 8 at 2 AM (this year in 2019) we are in UTC-7. In November, we do the opposite. In Nov 3 at 2 AM the clock is taken back one hour as the winter kicks in. At that point we are back in Standard Time. Seems a bit confusing but it's really not.
So, basically, for folks in PT they go from PST to PDT in March and from PDT to PST in November. The exact same process goes on with Mountain Time, Central Time and Eastern Time. But they have different UTC time offsets. MT is either UTC-6 or UTC-7. CT is either UTC-5 or UTC-6. And ET is either UTC-4 or UTC-5. All depending on whether we are in summer time when Daylight Saving is observed to make better use of daylight and working hours, or in winter time (AKA, Standard Time).
Study these thoroughly and understand how they work, and play around with the various time functions in Excel or Google Sheets like the TIME(#,#,#) and NOW() functions and such, and believe me, soon you'll be able to do about anything like a pro with plain functions without having to use VBA Google Apps Script. You can also use the TEXT() function, though, with tricks like =TEXT(L4,"DDD, MMM D")&" | "&TEXT(L4,"h:mm AM/PM"), where L4 contains you date-timestamp, to display time and date formats. The VALUE() function also comes in handy every now and then. You can even design a numerical countdown timer without the use of macros. You'd need to create a circular reference and set iterations to 1, and time display to say every 1 min, in your spreadsheet settings for that.
The official timeanddate dot com website is a good source of info for all to know about time zones and how daylight time is handled. They have all UTC offsets there too.
Create your own Timezone Converter in Google Sheets:
Step 1: Create your table for the timezone converter.
Step 2: Enter the times for your time zones in a column.
Note: Ensure that you select date/time format(Select Cell(s) -> Format -> Number -> Time/Date)
Step 3: Write a formula to convert timezone using the following functions
Google Sheet Functions
=HOUR(A8)+(B3*C3) converts the hours.
=MINUTE(A8)+(B3*C3) converts the minutes.
Step 4: Convert back to time format using TIME(h,m,s) function
=TIME(HOUR(A8)+(B3*C3), MINUTE(A8)+(B3*C3), SECOND(A8))
This is a simple way to convert timezones.
However, if you want to implement an accurate timezone converter that takes care of the previous day, next day, and beyond 24 hours, beyond 60 minutes, please use MOD operations and handle all the cases.
Visit(or Use) this google sheet for reference:
https://docs.google.com/spreadsheets/d/1tfz5AtU3pddb46PG93HFlzpE8zqy421N0MKxHBCSqpo/edit?usp=sharing
just use the TZData format to "pull" a sync from UTC and display your choice.
Example in order to "change" the display of your cell to Berlin local time
=fromUTC(N82, "Europe/Berlin")
or for Tokyo
=fromUTC(N82, "Asia/Tokyo")
or San Francisco
=fromUTC(N82, "America/Inuvik")
point of reference for Time Zones is here >>
https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

Retrieve Natural Time Intervals in MySQL for the client Time Zone

I have a PHP-MySQL API with Time Zone Support. My database is in UTC and all date time calculations are made in UTC time, just converting to local time when data is displayed to the user.
The problem is when trying to retrive data in a natural time interval for a user in a different time zone, for example weeks, months, years and so on. The DB column is type DateTime and store dates in UTC. If I need all rows grouped by month and just use the UTC date stored in the database I will get some wrong rows, if the Time Zone differences made some rows shift its month.
Example: row with value 2015-05-01 00:00:00 is in May in UTC, but should be in April for any user in a negative Time Zone.
So using UTC is not the solution here. I need first to convert those dates to client Time Zone.
Which aproach can I use to overcome this problem?
As an example this is view groups some data by week:
SELECT `individuals_id`,
Str_to_date(Concat(Yearweek(`sessions_date`, 5), ' Monday'), '%X%V %W') AS `sessions_date`,
`protocol_index`,
`zone_index`,
Avg(`asymmetry_dom`) AS `asymmetry_dom`,
Avg(`asymmetry_rl`) AS `asymmetry_rl`,
FROM `sessions_data_view`
GROUP BY `individuals_id`,
Yearweek(`sessions_date`, 5),
`protocol_index`,
`zone_index`
ORDER BY `individuals_id`,
Yearweek(`sessions_date`, 5),
`protocol_index`,
`zone_index`
The problem is that Yearweek() should have different output for a row depending on the user time zone. It is not posible to use the column sessions_date in UTC if want to give consistent result to the user.
Rigth now I do not know the user Time Zone, but this should not be a limitation, since the app is in its desing phase and anything can be changed.
The API is a PHP application getting HTTP requests. It talks to a PHP Database class that wraps all queries to the MariaDB database. All response from the aPI is given as JSON, dates formated as UTC strings. The data is shown via a web application. DateTime Javascript objects are responsible to convert the responses from the API to correct dates for the client time zone.
Firstly, the only reliable way you have of getting the client's timezone is through javascript, assuming their computer's time-settings are correct.
Solution One - Javascript to PHP
I suggest collecting the users timezone with the following javascript:
var timeZone = new Date().getTimezoneOffset();
You will need to store this value in the database. You then format the UTC time with PHP code similar to this:
$date = new DateTime();
$timezone = new DateTimeZone('Australia/Sydney');
$date->setTimezone($timezone);
$formatted_date = $date->format('Y-m-d H:i:s');
Solution Two - PHP to Javascript
You convert a UTC string into a unix timestamp with the following:
$time = strtotime($utc);
You then return that to the browser, and have javascript format it like this:
var date = new Date(timestamp * 1000),
datevalues = [
date.getFullYear(),
date.getMonth()+1,
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
];
Good luck!
edit: For converting MySQL for use with queries, use CONVERT_TZ, the format being:
CONVERT_TZ('date/time field','starting timezone','ending timezone')
For example:
select *, DATE_FORMAT(CONVERT_TZ(str_to_date(timestamp),'UTC','US/Eastern'), '%m/%d/%y %h:%i %p') as 'Date - Eastern' FROM table`

Rails localtime returns wrong time zone

I have a problem where when saving a datetime attribute, the form returns -04:00 instead of -05:00
Using Rails 3.2.3
In application.rb:
config.time_zone = 'Eastern Time (US & Canada)'
Using MySQL with mysql2 adapter
Running #wine.released_at.localtime returns 2008-05-15 00:00:00.000000000 -04:00
Running #wine.released_at returns 2008-05-15 04:00:00.000000000 Z
Running Time.now.zone returns Eastern Standard Time
Running #wine.released_at.zone returns EDT
I'm fairly confused. I though setting config.time_zone should make it such that Rails automatically converts all database datetime values to the set time_zone...why isn't this happening?
It looks to me as if the zone property returns the name of the "zone interval" which is applicable for the specified time. So for a summer time it will return "EDT" but for a winter time it will return "Easter Standard Time". (It's odd that it uses an abbreviation for one but not the other, but hey...)
So it is using the same time zone for both - those are just different aspects within the same time zone: sometimes it's standard time, sometimes it's daylight saving time.
If you print Time.now.localtime it should show you a -05:00 to show that the current offset from UTC in Eastern Time is -5 hours (i.e. Eastern Time is currently 5 hours behind UTC).
Have you tried using in_time_zone?

data type to use in mysql for timezones

I store a date/time in my database that is UTC. I'm working to add conversion of this once a user selects a timezone so it shows local time for them. Basically the user selects from a form:
<select name="DropDownTimezone" id="DropDownTimezone">
<option value="-12.0">(GMT -12:00) Eniwetok, Kwajalein</option>
<option value="-11.0">(GMT -11:00) Midway Island, Samoa</option>
<option value="-10.0">(GMT -10:00) Hawaii</option>
...
I can make the option value anything I want but an easy to remember one is as above. What data type would I use for mysql? Does it really matter in this case? Would TINYINT do? Maybe using an ENUM would be a good idea?
Any suggestions would be appreciated.
The scheme you're proposing (storing time zones as an integer offset from GMT) may fail for the following cases:
India, which is on UTC + 05:30 (not an integer number of hours).
Kiribati, which is on UTC + 14:00 (over 12 hours).
Distinguishing British Time and GMT. (The former uses Daylight Saving Time; the latter is not.)
Distinguishing between some pairs of countries which use the same GMT offset, but which switch at different times of the year.
For full time zone support, I'd recommend using the zoneinfo database and storing time zones as strings (e.g, "America/New_York").
Although this is very old. But for anybody still looking for the solution. I used
date-fns with time zones. I am using reactjs with node.js . Only had to add one extra column to the table - and always store time in UTC format only - and the corresponding zone in the additional column.
https://date-fns.org/v2.23.0/docs/Time-Zones
import { zonedTimeToUtc } from 'date-fns-tz'
const date = getDatePickerValue() // e.g. 2014-06-25 10:00:00 (picked in any time zone)
const timeZone = getTimeZoneValue() // e.g. America/Los_Angeles
const utcDate = zonedTimeToUtc(date, timeZone) // In June 10am in Los Angeles is 5pm UTC
postToServer(utcDate.toISOString(), timeZone) // post 2014-06-25T17:00:00.000Z, America/Los_Angeles
And for the scenario of timezones - list. https://www.npmjs.com/package/countries-and-timezones

Php-how to change timezone with daylight savings?

hey !
I'm working on a php web app , and i'm trying to change the time zone for each user according to his location ,
i was using this SQL statement : SET time_zone every time i'm about to display date and time ,
but when it comes to day light savings time , it does not work at all (ex : before daylight savings , timezone offset for Us&Canada Mountain time is -7 hours but now it's -8 hours and the code i'm using does not help at all ) ;
Thank you for you help
http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html,
The value can be given as a named time zone, such as 'Europe/Helsinki', 'US/Eastern', or 'MET'. Named time zones can be used only if the time zone information tables in the mysql database have been created and populated.
Seems to me that means you can use entries from the tz database such as America/Denver.
Note: Mountian is currently -6, not -8.