0

I have a date in the format "yyyy-mm-dd hh:MM:ss timezone" (i.e."2018-09-21 16:00:00 -0500") When use code:

var d = new Date("2018-09-21 16:00:00 -0500")

The debug shows me

d = Invalid Date

I am trying to reformat the date as below,

var days = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];


var day = days[d.getDay()];
var hh = d.getHours();
var mm = d.getMinutes()

if(hh < 10) {hh = "0"+hh}
if(mm < 10) {mm = "0"+mm}

return day+" "+hh+mm

What is the best way to format this date?

TheMaster
  • 45,448
  • 6
  • 62
  • 85
Brandon Hunt
  • 9
  • 1
  • 4

2 Answers2

3
  • You want to parse the string value of yyyy-mm-dd hh:MM:ss timezone as a date object.

If my understanding is correct, how about this answer? I think that there are several answers for your situation. So please think of this as one of them.

When I saw the format, I thought that RFC3339 is close to the format. So how about the following flow?

  1. Split the value by which is a space.
  2. Join 1st and 2nd element of the splited value by "T".
  3. Add last element to the joined value.

When 2018-09-21 16:00:00 -0500 is used for this flow, the value is converted to 2018-09-21T16:00:00-0500. This can be used as the RFC3339 type. By this flow, yyyy-mm-dd hh:MM:ss timezone can be parsed as the date object.

Sample script:

Pattern 1:

The sample script which reflected above flow is as follows.

var str = "2018-09-21 16:00:00 -0500"; // yyyy-mm-dd hh:MM:ss timezone

var ar = str.split(" "); // Added
var str = ar.slice(0, 2).join("T") + ar[2]; // Added: Here str is "2018-09-21T16:00:00-0500".
var d = new Date(str);

var days = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
var day = days[d.getDay()];
var hh = d.getHours();
var mm = d.getMinutes()
if(hh < 10) {hh = "0"+hh}
if(mm < 10) {mm = "0"+mm}

Logger.log(day+" "+hh+mm) // Added

return day+" "+hh+mm

Pattern 2:

As an another pattern, how about this script? In Google Apps Script, you can also use Utilities.formatDate().

var str = "2018-09-21 16:00:00 -0500";
var ar = str.split(" ");
var r = ar.slice(0, 2).join("T") + ar[2];
var d = new Date(r);
var res = Utilities.formatDate(d, Session.getScriptTimeZone(), "E hhmm").toUpperCase();
Logger.log(res)

Note:

  • If the format is different from yyyy-mm-dd hh:MM:ss timezone, this script might not be able to be used. Please be careful about this.

Reference:

If I misunderstand your question, I'm sorry.

Community
  • 1
  • 1
Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • 1
    A more relevant reference than RFC3339 is ECMA-262, since that is the language specification which specifies the formats that must be parsed and does not mention RFC3339. ;-) You could also do `"2018-09-21 16:00:00 -0500".replace(/([^\s]+) ([^\s]+) ([^\s]+)/,'$1T$2$3');`. – RobG Sep 20 '18 at 08:59
  • 1
    @rob kinda. Google uses RFC3339 for a lot of their APIs `datetime` objects. – tehhowch Sep 20 '18 at 11:37
  • @RobG Thank you for your advice. – Tanaike Sep 20 '18 at 11:51
  • @tehhowch Thank you for your support. – Tanaike Sep 20 '18 at 11:51
  • 1
    Sorry if I wasn't clear, I was talking about parsing in `new Date(r)`, not formatting. Though I take your point, Google variously claims Apps Script is [*"based on JavaScript"*](https://developers.google.com/apps-script/overview) and ["*is a JavaScript … scripting language*](https://www.google.com/script/start/)", so I guess I shouldn't get too precious about ECMAScript compliance since they don't claim it's a conforming ECMAScript implementation. – RobG Sep 20 '18 at 11:53
1

Your date is very close to ISO ! I would start by converting to ISO. For what you want, you don't need the timezone, so life will be simpler if we forget it...

var parts = '2018-09-21 16:00:00 -0500'.split(' ');
var myDate = new Date(parts[0] + 'T' +  parts[1] + 'Z');
console.log(myDate)

// Now serialize...

var nearlyThere = myDate.toLocaleDateString(
    'en-EN',
    {timeZone:'UTC', weekday:'short',hour:'2-digit',minute:'2-digit',hour12:false }
)
console.log(nearlyThere.replace(' ','').replace(':',' ').toUpperCase())
bbsimonbb
  • 27,056
  • 15
  • 80
  • 110
  • 1
    You've just changed the offset from -0500 to +0000. – RobG Sep 20 '18 at 08:54
  • I think I explained that? You don't need offset in the output, so I dropped it from the input. If you want to keep it in the input, do so, but then you need to remember it separately, and supply it to toLocaleDateString(). [Javascript dates have no notion of timezone](https://stackoverflow.com/a/38050824/1585345). – bbsimonbb Sep 20 '18 at 12:25
  • If the OP doesn't care about the timezone, I think it would be better to omit it and do everything as local as the *timeZone* option of *toLocaleString* is not that widely supported yet (and getting precise formatting with *toLocaleString* is problematic unless you get the parts one at a time). But I don't think it's sensible to ignore timezones, e.g. for someone in Auckland, New Zealand the OP timestamp is "Sat 0900" rather than "Fri 1600". – RobG Sep 20 '18 at 13:33
  • Local is worse ! If you leave off the Z (the ISO syntax for timezone not specified) Chrome will presume local time and Safari will presume UTC. Forcing UTC (both on the way in and the way out) is a kludge, but at least it gives a guaranteed correct outcome. – bbsimonbb Sep 20 '18 at 15:02
  • @RobG My thing works for someone in New Zealand. You get the same time out as you put in. The OPs input format has a timezone offset, but his output doesn't require one, so I'm excluding it at the beginning, rather than carrying it through then ignoring it. – bbsimonbb Sep 20 '18 at 15:07
  • Re "*Local is worse*", I'm aware of Safari's buggy behaviour so would use the constructor, not the built–in parser. Anyway, I think there's enough here for the OP to work things out. :-) – RobG Sep 20 '18 at 20:22