Related
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
In IE if you write in the console new Date("22/22/22") you get the answer of Mon Oct 22 00:00:00 CDT 1923
In Chrome it says Invalid Date.
What is happening here and why?
What is happening here and why?
What's happening is you're running into undocumented behavior. The only string format the Date constructor is required to support is the ISO-8601 simplification in the specification, which your example does not match. Everything else is undocumented and JavaScript engines are at liberty to do whatever they want, including guessing at the format you're giving them (and doing JavaScript's nifty rollover when you take a value like 'month number' out of bounds), or giving you an invalid date.
If you're curious about the rollover, IE's treating that as the 22nd day of the 22nd month of the year 1922. Naturally, years don't have 22 months, but JavaScript's Date is defined as handling rollover in various fields, such as month number, gracefully. So the 22nd month of 1922 is actually the 10th month of 1923, and of course, you're on the 22nd day of it: October 22, 1923.
IE 11 and Firefox 42 translates the value 22 for month to 12+10.
Chromium throws a error.
Different JS engine implementations gives different results for invalid values.
I need current month name as default perameter name in my ssrs report. How can I get current month name using an ssrs expression?
For example "27-09-2012" would become "September"
and one more i need....
27-09-2012 to previous month name as well (August)
First question:
=MonthName(Month(Fields!datefield.Value))
Second question:
=MonthName(Month(DateAdd("m", -1, Today())))
I think the second question answer might be something like that, first converting the date to month then subtracting 1 from the month value and then converting it to month name.
Further reading:
SSRS Reports get Month name from Month Index or from date
Converting month number to month name in reporting services
OFF: I would change the date format you are using to 2012-09-27 as it works in every setting and should give you peace of mind when converting date formats.
Don't subtract 1 b/c it won't work for January.
Use this:
MonthName(Month(DateAdd("m", -1, CDate(Today))))
As a note, I tried the suggestion of =MonthName(Month(today())). What I would get is #error for whatever field the expression was in. However, =MonthName(str(Month(today()))) worked for me. I am unsure of whether or not the MonthName method changed to require a string or if it is some issue with my program. Just figured I would post this in case anyone else was having the same issue.
For Previous Month i found universal way : =MonthName(Month(CDate(Today()))-1,False) for SEPTEMBER (Full Month Name) 'OR'
=MonthName(Month(CDate(Today()))-1,True) for SEP (Short Month Name)
I'm using Access 2003. Have a table with some date values in a text data column like this;
May-97
Jun-99
Jun-00
Sep-02
Jan-04
I need to convert them to proper date format and into another Date/time column, So create a new Date/Time columns and just updated the values from the Text column into this new column. At first it looked fine, except for years after the year 2000. The new columns converted the dates as follows;
May-97 > 01/05/1997
Jun-99 > 01/06/1999
Jun-00 > 01/06/2000
Sep-02 > 01/09/2010
Jan-04 > 01/01/2010
As you can see any data with year after 2000 get converted to 2010. The same thing happens if I query the data using FORMAT(dateString, "dd/mm/yyyy").
Any ideas why this is so? Do I have to split the month and year and combine them again?
Thanks
Access/Jet/ACE (and many other Windows components) use a window for interpreting 2-digit years. For 00 to 29, it's assumed to be 2000-2029, and for 30-99, 1930-1999. This was put in place to address Y2K compatibility issues sometime in the 1997-98 time frame.
I do not allow 2-digit year input anywhere in any of my apps. Because of that, I don't have to have any code to interpret what is intended by the user (which could conceivably make mistakes).
This also points up the issue of the independence of display format and data storage with Jet/ACE date values. The storage is as a double, with the integer part indicating the day since 12/30/1899 and the decimal part the time portion within the day. Any date you enter is going to be stored as only one number.
If you input an incomplete date (i.e., with no century explicitly indicated for the year), your application has to make an assumption as to what the user intends. The 2029 window is one solution to the 2-digit year problem, but in my opinion, it's entirely inappropriate to depend on it because the user can change it in their Control Panel Regional Settings. I don't write any complicated code to verify dates, I just require 4-digit year entry and avoid the problem entirely. I have been doing this since c. 1998 as a matter of course, and everybody is completely accustomed to it. A few users squawked back then, and I had the "it's because of Y2K" as the excuse that shut them down. Once they got used it, it became a non-issue.
The date is ambiguous, so it is seeing 02 as the day number. Depending on your locale, something like this may suit:
cdate("01-" & Field)
However, it may be best to convert to four digit year, month, day format, which is always unambiguous.
Access seems to be get conduced between MM-YYYY format and MM-DD format. Don't know why it is doing it for dates after the year 2000, but solved it by converting the original string date to full date (01-May-01). Now Access converts the year into 2001 instead of 2010.
If you don't supply a year and the two sets of digits entered into a date field could be a day and month then Access assumes the current year. So your first three dates definitely have a year in them. But the last two don't.
Note that this isn't Access but actually the operating system doing the work. You get the same results in Excel. I had an interesting conversattion with some Microsoft employees on this issue and it's actually OLEAUT32.DLL.
Examples:
'DD/MM/YYYY
"1/1/2009" should give `1`
"31/1/2009" should give `5`
"1/2/2009" should also give `5`
Format("1/2/2009", "ww") returns 6.
So, how can I get the correct result?
It's doing two things here which don't match your expectations, I think:
Assuming you want the week with Jan 1 in as week 1, and using Sunday as first day of the week
So it has week 1 running from Sunday 28th December 2008 to Saturday 3rd Jan 2009.
Week 6 would begin on Sunday 1st Feb by this method.
The ISO standard is for week 1 to be the one containing 4 days of January, or the first Thursday of the year (different ways of expressing the same thing).
You can specify this method of calculation and the first day of the week:
Format(SomeDate,"ww",vbMonday,vbFirstFourDays)
see here for syntax:
https://support.office.com/en-US/article/Format-Function-6F29D87B-8761-408D-81D3-63B9CD842530
Regardless of the day of the week your week starts on, you need to pass unambiguous date values. "31/1/2009" can only be one date (Jan 31st), but "1/2/2009" could be Jan. 2 (US style) or Feb. 1st (everybody else who has more sense that we USAns).
In this case, I'd use DateSerial() to make sure the date is not misinterpreted:
Format(DateSerial(2009,2,1), "ww", vbMonday)
While this is not causing your problem, because Access helpfully utilizes your system's localized date settings, I think it's something you should do anyway. You certainly are forced to do so in SQL in Access, so I don't think it's a bad habit in code and expressions.
This might work: Format(YourDate, "ww",vbMonday)
"Correct result" depends on the locale. Maybe VBA will let you pick a calendar-system, otherwise you're pretty much out of luck.
Note that First-Day-On-xxDay isn't your only problem. There is also variation on what a complete week is so Week 1 in one system could be Week 53 of the previous year in another system.
So test thoroughly and don't be seduced to "correct by 1".
There is a whole standard for week numbers: ISO-8601
http://en.wikipedia.org/wiki/ISO_8601#Week_dates
I had the same problem.
It showed week 53 and week 1, yet days in week 53 and week 1 are all in week 1
I first tried changing the date format in the Access Query to this:
OrderWeek: Format([OrderDate],"yyyy-ww",1,3) <-- But it did not do the trick.
You get dates like 2014-52 for week 52 and 2015-52 where it was week 1 before.
Also the sorting was not how I liked. It sorted the data as 2014-1, 2014-11, 2014-2 etc. I want it to show as 2014-01, 2014-02 .. 2014-11 etc.
So here is the new code to display both the year and the week correctly in an Access Query:
ActualWeek: IIf(DatePart("ww",[SomeDate])=53,DatePart("yyyy",[SomeDate])+1,DatePart("yyyy",[SomeDate])) & "-" & IIf(DatePart("ww",[SomeDate])=53,"01",IIf(DatePart("ww",[SomeDate])<10,"0" & DatePart("ww",[SomeDate]),DatePart("ww",[SomeDate])))
This now shows any days from week 53 as being part of week 1
If sunday is the first day of the week (as it is in some locales) then 6 is the correct weeknumber for "1/2/2009" (february 1. 2009)
In terms of the sorting, I had the same issue and used this code to resolve it:
IIf(Format([SomeDate],"ww")<10,Format([SomeDate],"yyyy-") & "0" & Format([SomeDate],"ww"),Format([SomeDate],"yyyy-ww"))
If the week number is less than 10, add a zero, else leave it as is.
Now the sorting is fine. Hope this helps somebody.