I'm using Google Spreadsheets and I have a sheet in the following format:
Start | End | Partial result | Expected | Total
08:00 | 12:00 | 04:00 | 05:00 | -01:00
14:00 | 18:00 | 04:00 | 05:00 | -01:00
----------------------------------------------------
| Month tot| -02:00
As you can see, it allows for negative duration stamps. This is causing me a lot of trouble in Google Scripts.
I want to email everyone a monthly summary.
Here's a simple snippet:
var sheet = SpreadsheetApp.getActive().getSheetByName(...);
var monthlyTotal = sheet.getRange(1, 1).getValue(); //The total is at cell A1
Now, when I debug, it shows my monthlyTotal as a Date
object, set to Tue Dec 26 1899 14:50:28 GMT-0300 (BRT)
(this is quite correct, my result is -81:16:00
, it subtracted 81:16
from 1900-01-01 00:00:00
, no issues there).
Now, I have no idea how to get back to a duration format (-81:16
). I have tried converting this date object to a negative timestamp, but +monthlyTotal
returns what I believe to be a wrong value (-2212132172000
).
I have no idea how to turn a Date
object from before 1900 to a timestamp and, as a consequence, I don't know how to proceed.
Best Answer
Short answer
Don't use
.getValue()
on date/time cells. Instead, put=TO_TEXT(A1)
somewhere (or already have A1 containing something likeTO_TEXT(SUM(E2:E))
, and use.getValue()
to get that string. Numbers and strings pass between sheets and scripts reliably, unlike dates and times.Explanation
Unlike the Unix operating systems for which the epoch begins at 1970-01-01, Google Sheets use
December 30, 1899 0:00:00
as 0 time, which you can see by entering=TO_DATE(0)
anywhere in your spreadsheet.In principle, you could apply
.valueOf()
to the duration value returned by.getValue()
: this returns the JavaScript timestamp, which is the number of milliseconds from the beginning of 1970. Dividing by 1000 gives the Unix timestamp.However, this is problematic because Unix timestamp and consequently JavaScript timestamp are measured from the moment
1970-01-01 00:00:00
in UTC, while the 0 mark of Google Sheets is in the local timezone.If you try to adjust for timezones using
new Date().getTimezoneOffset();
be warned that script time zone may be different from sheet time zone: documentation says this is "a frequent source of scripting bugs". The methodSpreadsheet.getSpreadsheetTimeZone()
gives the timezone of Spreadsheet itself, but it's returned as a string like 'America/New York', which does not directly translate to an offset.