0

DESCRIPTION: I want to convert a DD/MM/YYYY HH:mm or 25/01/2022 11:00 string, in an accepted date format. Doesn't matter which one, it just has to be recognized by Apps Script and Google Sheets and be able to work with it.

If you can provide an Apps Script's code (not a formula in Google Sheets like I attempted to do) that converts the string into a date and then set the values in another range, to work with them as dates, I would be grateful, thanks.

If it's a Google Sheet formula no problem, as long as it works.

TRIED: After many attempts, I tried to build a custom formula putting pieces together around the web but it doesn't function

//formula is translated from italian
=ARRAYFORMULA(IF(F10:F="",,TEXT(DATE(
 IF.ERROR(REGEXEXTRACT(F10:F, "/(\d+) "), YEAR(F10:F))*1, 
 IF.ERROR(REGEXEXTRACT(F10:F, "/(\d+)"), MONTH(F10:F))*1,
 IF.ERROR(REGEXEXTRACT(F10:F, "\d+"),   DAY(F10:F))*1)+
 IF.ERROR(TIME.VALUE(F10:F), REGEXEXTRACT(F10:F, "\d+:\d+")+
 IF(REGEXMATCH(F10:F, "PM"), 0.5, 0)), "yyyy-mm-dd hh:mm")))

It gives a #VALUE error, which says "'11:00' is a string and can't be recognized as a date" (11:00 is an example).

I've also got the Regular Expression, but I don't know if it's correct and how to use it in code:

/([\d])\w+\/([\d])\w+\/([\d])\w+\s([\d])\w+\:([\d])\w+/g

I also tried changing the time zone but it didn't work. Keep in mind I'm using the Italian time zone, if it's possible I'd rather keep it as it is.

Table example (like I said, what's important is that dates are accepted as dates):

F: Column source strings
Q: Column desired dates recognizable as dates by Sheets (Q because it's the real column where I want to put the formula)

F .. Q
16/02/2023 16:00 16/02/2023 16:00:00
25/11/2022 15:00 25/11/2022 15:00:00

For @Cooper and the solution based on the script.

I've customized the script, but it doesn't recognize the split function anymore (copy and paste of your function logs what it expects in Apps Script), and doesn't get any results in overwriting the existing string dates.

let dateStringed; //source wrong dates 
var i = 0;
var flatArray;
function expired() {
  
  //bLast is the range Last Row
  dateStringed = gen.getRange(10, 6, bLast, 1).getValues(); 
  flatArray = [].concat.apply([], dateStringed);
  while (i <= bLast) {
    i++;
    convert();
  };
Logger.log(flatArray);
gen.getRange(10, 6, bLast, 1).setValues(flatArray);
};

function convert(s=flatArray[i]) {   //instead of "25/01/2022 11:00"
  let [d,m,y,hr,mn] = s.split(/[\/ :]/)
  Logger.log('y: %s m: %s d: %s hr: %s mn: %s',y,m,d,hr,mn);
  Logger.log(new Date(y,m - 1,d,hr,mn).toLocaleString());
  //don't know if it's correct, but it logs the dates
  //in an easier syntax
};

For @doubleunary solution:

Demo SHEET ITA

In the sheet I copied and pasted the first column of my private original sheet, the F column with the text dates, and the Q10 cell I've pasted the formula as it is

I made sure to set local to Italy but to display english name formulas. I don't know why, here it colors green and it doesn't give me a result.

But I did a test, and set the sheet tu US time and it functions. Any idea on how to make it function in Italian version?

Demo SHEET US

Solved: I used this script

    function dateCorrected(){  
  
     gen.getRange('N10:N').clearContent();
//get the formula from another code sheet:
 //'=arrayformula( SE.ERRORE( 1 / VALORE( 
 //regexreplace( to_text(F10:F); 
 //"(\d+)/(\d+)/(\d+) (\d+):(\d+)"; "$3-$2-$1 $4.$5" ) ) ^ -1 ) )'
      var dateCorr = codeSheet.getRange('T1').getFormula();
      Logger.log(dateCorr);
      gen.getRange('N10').setFormula(dateCorr);
      gen.getFilter().sort(14, false);
      gen.getRange('N10:N').clearContent();
      gen.getRange('N10').setFormula(dateCorr);
    }

And this gives me the possibility to delete rows that meet a certain date condition. Thank you all for the support.

  • Welcome to [Stack Overflow](https://stackoverflow.com/tour). Working with datetime values is more complex than one would initially expect. Please show a [table](https://stackoverflow.com/editing-help#tables) of sample text string dates together with a [table](https://stackoverflow.com/editing-help#tables) that shows your manually entered desired results. – doubleunary Dec 16 '22 at 18:13
  • @doubleunary updated! I'm preparing it for your solution, thanks for the idea – user20749937 Dec 16 '22 at 21:28
  • Checked, is text. I need them as dates, because then I want to delete all the rows with a date before today. I knew they were strings cause the didn't want to be filtered the proper way – user20749937 Dec 16 '22 at 21:55

4 Answers4

0

Convert String to Date:

function convert(s="25/01/2022 11:00") {
  let [d,m,y,hr,mn] = s.split(/[\/ :]/)
  Logger.log('y: %s m: %s d: %s hr: %s mn: %s',y,m,d,hr,mn);
  Logger.log(new Date(y,m - 1,d,hr,mn));
}

Execution log
10:58:11 AM Notice  Execution started
10:58:12 AM Info    y: 2022 m: 01 d: 25 hr: 11 mn: 00
10:58:12 AM Info    Tue Jan 25 11:00:00 GMT-07:00 2022
10:58:13 AM Notice  Execution completed
Cooper
  • 59,616
  • 6
  • 23
  • 54
  • Thank you for your suggestion. I tried using your script in a custom way, to pass the array with the string dates in the convert function as items, but maybe I'm missing something, because the split fucntion isn't recognized in the way I use it, can you take a look? I'll edit the main question. – user20749937 Dec 16 '22 at 21:24
  • Just pass the string as a parameter. There's only one parameter. I'm just providing a default value for my work but if you pass it another value that's the value it will use. I created the string based on your queestion `day/month/year hour:minute` or as you put `dd/MM/yyyy HH:mm` – Cooper Dec 16 '22 at 21:28
  • I've updated the question with the faulty code – user20749937 Dec 16 '22 at 21:52
  • You don't seem to understand how to implement default parameters in ECMA Script 2015. You don't need to use `s = flatArray[i]` just go with convert(flatArray[i])` as long as the flatarray is an array of strings in the correct format which I can't tell from you code – Cooper Dec 16 '22 at 21:57
  • Thank you, in fact I started using Apps Script 3 weeks ago and my head is exploding, I try to make functions run in the bizzarre ways, but I learn along. "flatArray" is the flattened array with the dates as text(dateStringed array), which I have to convert in correct dates as your formula do. If I can implement your formula it would be good cause it seems fast. – user20749937 Dec 16 '22 at 22:28
0

It is usually easiest to do the text string to datetime conversion using a spreadsheet formula. You can convert text strings like 25/01/2022 11:00 to dates with this formula in cell G10:

=arrayformula( iferror( 1 / value( regexreplace( to_text(F10:F); "(\d+)/(\d+)/(\d+) (\d+):(\d+)"; "$3-$2-$1 $4.$5" ) ) ^ -1 ) )

Format the result column as Format > Number > Date time.

In the event you need to "fix" those datetime values in place, you can replace the formula results with static values with Control+C to copy and Control+Shift+V to paste values only, or do the same with a simple range.setValues(range.getValues()) script bit.

In the event you need to pass those datetime values to Apps Script, it is usually easiest to get them as Date objects rather than text strings. The Date objects will refer to the same moment in time (in UTC) as the date times in the spreadsheet (in the spreadsheet's time zone).

You should note that Apps Script is JavaScript which means that Date objects are always in the UTC timezone. If you log them or output them in some other way, they will not be shown in the Italian timezone as you expect.

There are two easy ways to present such dates in a human-readable format in the spreadsheet's timezone. The first is to directly get the data as a text string in the format that it is shown in the spreadsheet:

function test1() {
  const ss = SpreadsheetApp.getActive();
  const dateStrings = ss.getRange('Sheet1!G10:G')
    .getDisplayValues()
    .flat()
    .filter(String);
  console.log(dateStrings);
}

The second is to get the data as Date objects and convert them to text strings using the spreadsheet's timezone, like this:

function test2() {
  const ss = SpreadsheetApp.getActive();
  const timezone = ss.getSpreadsheetTimeZone();
  const dates = ss.getRange('Sheet1!G10:G')
    .getValues()
    .flat()
    .filter(String)
    .map(date =>
      Object.prototype.toString.call(date) === '[object Date]'
        ? Utilities.formatDate(date, timezone, 'dd/MM/yyyy HH:mm')
        : date
    );
  console.log(dates);
}
doubleunary
  • 13,842
  • 3
  • 18
  • 51
  • Thank you for the suggestion. I have a problem with your first Google Sheet formula. If I paste it in an US Sheet, and use some test string dates, copied from the source sheet, it functions, and also colors the cells of green (?). But then, if I copy it in my sheet, and put the ";" in place of the "," to match Italian syntax, Sheets automatically translate in the correct way the function, but it doesn't show results. I've tried to put it exactely in column G but nothing happens, any idea? – user20749937 Dec 16 '22 at 21:21
  • Don't know what happened there with the green, ignore it. Now I'll post the example sheet where your formula functions. The error it gives me is "The parameter "2023-02-16 16:00" of VALUE can't be analyzed as number" (source string: 16/02/2023 16:00). – user20749937 Dec 16 '22 at 21:48
  • Edited the answer to use `.` instead of `:` as hours.minutes separator. – doubleunary Dec 16 '22 at 22:30
0

To convert a string to a Date object in Google Apps Script use Utilities.parseDate.

Example:

function myFunction(){
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const timeZone = spreadsheet.getSpreadsheetTimeZone();
  const date = Utilities.parseDate('25/01/2022 11:00',timeZone, 'dd/MM/yyyy HH:mm');
  return date;
}

Using the above as a custom function might not make sense for some use cases since the same result might be achieved by using built-in functions which are more efficient and less prone to have problems.

The options for using built-in functions depends on the spreadsheet settings, i.e. DATEVALUE might return different results for ambiguos dates like 25/01/2022 as for certain regions the month goes first and for others the day of the month goes first.

=DATEVALUE("25/01/2022") works correctly when the spreasheet region is set to Italy. You might have to manually set the cell formatting to date in order to make it show a date instead of the time serialized value (a number).

To convert 25/01/2022 11:00 using formulas in the above spreadsheet, use

=INDEX(SPLIT("25/01/2022 11:00";" ");1) + SUBSTITUTE(INDEX(SPLIT("25/01/2022 11:00";" ");2);":";".") 

The above formula has two main parts joined by using +. The first part returns the time serialized value corresponding to the date, the second part returns the time serialized value corresponding to the time.

Array formula

=ArrayFormula(DATEVALUE(REGEXEXTRACT(F10:F;"^([ˆ\d/]+) "))+TIMEVALUE(SUBSTITUTE(REGEXEXTRACT(F10:F;" ([ˆ\d/:]+)$");":";".")))

The same concept as the previous formula, but instead of INDEX it uses REGEXEXTRACT.

Rubén
  • 34,714
  • 9
  • 70
  • 166
  • Yes, the script gives a weird time, but a correct date. The formula is correct, it gives me the date recognized. Thank you for the effort, the explanation is helpful. I surrended and asked here after some days on the research, sometime you have to get the exact method and formula or you don't get out of the loop – user20749937 Dec 16 '22 at 23:14
  • What do you mean by "the script gives a weird time"? (p.s the script had a pair of typos, missing on spreadsheet, fixed now) I just test it and is working fine. – Rubén Dec 16 '22 at 23:34
  • `const date = Utilities.parseDate('25/01/2022 11:00',timeZone, 'dd/MM/yyyy HH:mm'); Logger.log(date);` it gives this as output: `Tue Jan 25 05:00:00 GMT-05:00 2022` and it should be 11 o'clock, is the time zone incorrect in formula? – user20749937 Dec 17 '22 at 00:14
  • Don't use Logger.log / console.log to log dates if you aren't familiar with how this statements convert Dates objects to strings. – Rubén Dec 17 '22 at 00:18
  • So I should check results directly in the spreadsheet? – user20749937 Dec 17 '22 at 00:19
  • You could use the debugger but checking the results directly in the spreadsheet should work too. If you want to learn more about how to use Logger / console to log dates see https://stackoverflow.com/a/71340799/1595451 – Rubén Dec 17 '22 at 00:21
  • Thanks Rubén for mentioning the recently introduced `Utilities.parseDate()`. Regarding your rexeges — there is a superfluous character in `[ˆ\d/]` that looks like circumflex (caret) `^` but isn't. It is actually a Modifier Letter Circumflex Accent (Unicode 710) and has no special meaning in a regex. It does not appear in the data in this use case so it will not affect the results. – doubleunary Dec 17 '22 at 06:17
-1

Google has a Utility to do just that!

let dateTime = '2022-12-16 13:00:00';
let timeZone = 'GMT';
let convertedDateTime = Utilities.formatDate(dateTime, timeZone, 'dd/MM/yyyy HH:ss')

check out Class Utilities for more info.

  • Thank you. The problem is that I have to get from a string, a recognizable date format that now it doesn't want to give me, and that formula didn't help me. I'll post soon an example sheet so it will be easier to identify the problem. – user20749937 Dec 16 '22 at 21:51
  • The first parameter of Utilities.formatDate should be a Date object, not a string. – Rubén Dec 16 '22 at 22:34