-1

Details

In my Google Sheet I have a column that has been formatted in the 03:59 PM format. When I insert time into it, the data is correctly formatted as 00:00 AM automatically, but not with the correct date, as it says it's from the year 1899.

When I insert data and specify the date first, it overwrites the columns 00:00 AM format and instead inserts a MMM DD YYYY 00:00 format with the month being text, day and year in numbers, and no AM or PM. When I manually format the cell (or whole column) again with 03:59 PM format, it shows the right time format and has the correct date.

I'm currently adding data via a Python script with the Gspread module. This allows me to format it with a specified pattern. The data is added to a cell as a date time string, which then changes the cell's formatting, but then immediately after that individual cell is overridden again into a hh:mm AM/PM pattern format: {"numberFormat": {"type": "DATE_TIME", "pattern": "hh:mm AM/PM"}}.

Therefore right now only when manually typing in data, it isn't overridden immediately after like the Python script.

Question

How can I insert data into a sheet that has a date time property (or at least contain both the date and time), while not overwriting the column's 00:00 AM formatting?

Have tried:

  • Formatting the entire column and then entering data
  • Entering data with various formats, like 12/12/2021 3:00 PM which adds the PM but still overwrites just the time format.

enter image description here

Nuxurious
  • 79
  • 12
  • Why not just enter and format later? – TheMaster Dec 14 '21 at 19:15
  • Because I want to automatically add an entry to this sheet every day, and not manually re-format it. – Nuxurious Dec 14 '21 at 19:25
  • Could you explain what you meant by `automatically`? `onEdit` won't work, if the input is from Python – TheMaster Dec 14 '21 at 20:07
  • Just edited the original question given some more details. I'm not that familiar with apps-script, but onEdit might do the trick. Will have to figure out how to edit only manual data though, instead of re-formatting an individual cell twice. – Nuxurious Dec 14 '21 at 20:39

2 Answers2

1

Here is the rather clumsy solution, but probably it will work for you:

function onEdit(e) {
  if (e.range.columnStart != 2) return; // if it's not column B do nothing

  var value = e.range.getDisplayValue();
  if (value.length < 12 && value.length > 0) {
    var tz = Session.getTimeZone();
    var today = Utilities.formatDate(new Date(), tz, 'yyyy-MM-dd');
    var date = Utilities.formatDate(new Date(today + ' ' + value), tz, 'yyyy-MM-dd hh:mm a');
    e.range.setValue(date);
    e.range.setNumberFormat('hh:mm am/pm');
  }
}

It sets current year, month and day for any 'date' that is shorter than 12 letters (it supposes that this 'date' is a time).

Probably you want to move the last line e.range.setNumberFormat('hh:mm am/pm'); down, out of {}. In this case it will format all inputted 'dates' as time hh:mm.

function onEdit(e) {
  if (e.range.columnStart != 2) return; // if it's not column B do nothing

  var value = e.range.getDisplayValue();
  if (value.length < 12 && value.length > 0) {
    var tz = Session.getTimeZone();
    var today = Utilities.formatDate(new Date(), tz, 'yyyy-MM-dd a');
    var date = Utilities.formatDate(new Date(today + ' ' + value), tz, 'yyyy-MM-dd hh:mm a');
    e.range.setValue(date);
  }
  e.range.setNumberFormat('hh:mm am/pm');
}

Update

Here is a little bit less clumsy variant of the same solution:

function onEdit(e) {
  if (e.range.columnStart != 2) return; // if it's not column B do nothing

  var date = e.range.getValue();

  if (date.getFullYear() < 1990) {
    var time = e.range.getDisplayValue();
    var tz = Session.getTimeZone();
    var today = Utilities.formatDate(new Date(), tz, 'yyyy-MM-dd a');
    var new_date = Utilities.formatDate(new Date(today + ' ' + time), tz, 'yyyy-MM-dd hh:mm');
    e.range.setValue(new_date);
  }

  e.range.setNumberFormat('hh:mm am/pm');
}

It changes year, month, day to current date if the automatically assigned year less than 1990.

Yuri Khristich
  • 13,448
  • 2
  • 8
  • 23
  • I don't think you need to format date at all. Just `setValue(new Date()).setNumberFormat('hh:mm am/pm')` – TheMaster Dec 14 '21 at 22:20
  • Hm... @TheMaster I failed to implement it. What do you mean? Can you show a working piece of code. In my code the formatting is need to get the two strings: 'yyyy-MM-dd' and 'hh:mm am/pm' then I concatenate them to get correct date. Frankly, I'm not an expert in Data.object, to say the least. And I hope there is a more efficient solution. It would be great if you provide it. – Yuri Khristich Dec 14 '21 at 23:56
  • I didn't fully see your concatenation. I'm sure you can directly work with date objects though. Checkout https://stackoverflow.com/questions/17715841/how-to-read-the-correct-time-duration-values-from-google-spreadsheet – TheMaster Dec 15 '21 at 00:46
  • 1
    I think something like this will work: ```const [h, m, s] = ['Hours','Minutes','Seconds'].map(s => e.range.getValue()[`get${s}`]()); e.range.setValue(new Date(new Date().setHours(h,m,s,0)))``` – TheMaster Dec 15 '21 at 01:31
  • @TheMaster my 'concatenation': new Date(**today + ' ' + time**) (`today` and `time` are strings here). As for the rest -- that's the nice trick, thank you, but I still can't see how it helps to solve the task: to get '12/15/2021 03:00 AM' when you input '3:00 AM'. By default it gets '12/30/1899 03:00 AM'. And it changes the hh:mm (in my timezone, at least) if you try to change the year from '1899' to '2021' directly via `date.setFullYear('2021')` – Yuri Khristich Dec 15 '21 at 08:32
  • 1
    I mean we're not trying to setFullYear on the original date(while that is possible), my code is trying to copy `3:00`[3h,00m,0s] to a ``new date()``,If timezone is not a issue , i.e., at least h,m,s are preserved on the original date. If tz changes, we need to fix session tz to spreadsheet tz. – TheMaster Dec 15 '21 at 08:36
  • 1
    @TheMaster Well. Now I get it. It changes hh:mm (instead of year) in more neat way. But it looks like I have the hasty troubles with timezones (my timezone Moscow, Russia GMT+03, and I have no idea about daylight saving, probably it's there as well). I just tried your code https://pastebin.com/qZa0exeh (in new spreadsheet) and when I'm input '22:22' it gets me the date '12/15/2021 22:51:43' (time offset 29 min 43 sec! probably it has to do with dates in Russian Empire around 1900s). This is exactly why I prefer to use strings. I would be grateful if you show me, how it should be done properly. – Yuri Khristich Dec 15 '21 at 10:54
  • @TheMaster from this discussion https://stackoverflow.com/questions/57296496/weird-time-offset-dealing-with-date-time-and-timezone I tend to think that to play with strings (getDisplayValue(), etc) is still the most reasonable solution for such cases. At the end of the day. :) – Yuri Khristich Dec 15 '21 at 12:04
  • 1
    I agree it's probably the easiest in this case, but generally, you should avoid strings as dates. Even in this case, I would probably suggest using dates. I think probably using a offset based on the date `new Date(1899,11,30)` will work in all cases, but I didn't test it and I don't want to waste your time more too. If I do test and find a way, I'll add a comment or edit/add a another answer. – TheMaster Dec 15 '21 at 12:31
0

Clear B2:B and in B2:

={A2:A}

You can then enter the full date in A2:A and see expected formatting in B2:B

  • Raw data: A2:A
  • Presentation: B2:B

You can also separate raw data and presentation to separate sheets.

TheMaster
  • 45,448
  • 6
  • 62
  • 85
  • That's not what I was going for since this sheet is used for data input and presentation already, not raw data, so 2 columns isn't ideal in this case. – Nuxurious Dec 14 '21 at 19:46
  • @Nuxurious Since you tagged script, I guess you were going for a `onEdit` script. Can you provide what you've tried in scripting so far? – TheMaster Dec 14 '21 at 19:56
  • Nothing in scripting yet, but in a Python automation I've been able to reformat with the right pattern when inserting a date time string. This way, it inserts the string, changes the column's formatting, but then reformats the cell immediately again. But this isn't the case for manual input yet. – Nuxurious Dec 14 '21 at 20:04