1

Basically my goal is to parse a string into a Date properly, I have most of the work done as in I get the Date and time into a JavaScript Date object, but I'm unsure of how to parse and apply the timezone.

The EventBrite API which I'm working with returns a String for both start_date and for timezone_offset:

timezone_offset: "GMT-0500"

start_date: "2013-04-27 19:00:00"

I'm parsing the start_date using this code which seems to work well:

var sd = response.events[i].event.start_date;
var parsedSD = sd.split(/[:-\s]/);
var startDate = new Date(parsedSD[0], parsedSD[1]-1, parsedSD[2], parsedSD[3], parsedSD[4], parsedSD[5]);

The part I'm missing is how to parse the timezone_offset or otherwise apply it to the Date so if I show the time/date in local time it's correct?

Any tips appreciated, my initial thought is to take a sub string of the last five characters then use that to offset the time using a combo of getTime/setTime.

Honestly, this isn't crucial since most people planning to attend an event will be in the same timezone or I could just display the timezone_offset but I would like to know how to do this properly anyhow.

EDIT 1

Here's my current code, I put in comments to say what Safari thinks the values are:

var timezone_offset = response.events[i].event.timezone_offset; //timezone_offset is "GMT-500"
var sd = response.events[i].event.start_date+timezone_offset; //sd is "2013-04-27 19:00:00GMT-500"
var dt_iso8601 = sd.replace(/ /, 'T').replace(/GMT/,''); //dt_iso8601 is "2013-04-27T19:00:00-0500"
var startDate = new Date(dt_iso8601); //startDate is Invalid Date

EDIT 2

For anyone who finds this and is having this specific problem here's the full solution I'm using to leave out any events that were in the past (since currently it appears the EventBrite API doesn't give you a way to do this). This is an AngularJS controller I'm working on but the JS should mostly apply in any context:

[index.php]

<script src="scripts/moment.min.js" type="text/javascript"></script>
<script src="scripts/Eventbrite.jquery.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.js"></script>
<script type="text/javascript" src="eventDirective.js"></script>

[eventDirective.js]

function EventCtrl($scope)
{   
    $scope.events=[];
    $scope.noEventsDisplay = "Loading events...";

    Eventbrite({'app_key': "YOURAPPKEYHERE"}, function(eb){

        // define a few parameters to pass to the API
        // Options are listed here: http://developer.eventbrite.com/doc/organizers/organizer_list_events/
        var options = {
            'id'    : "your_organizer_id_here",

        };

        // provide a callback to display the response data:
        eb.organizer_list_events( options, function( response ){
            validEvents = [];
            var now = moment();
            for(var i = 0; i<response.events.length; i++)
            {
                var timezone_offset = response.events[i].event.timezone_offset;

                var ed = response.events[i].event.end_date+timezone_offset;
                var em = moment(ed,format);

                //if older than today skip
                if(em<now)
                    continue;
                var sd = response.events[i].event.start_date+' '+timezone_offset;
                var format = 'YYYY-MM-DD HH:mm:ss [GMT]ZZ';
                var sm = moment(sd,format);

                response.events[i].event.formattedDate = sm.toDateString();
                validEvents.push(response.events[i])
            }
            if(validEvents.length == 0)
            {
                $scope.$apply(function(scope){scope.noEventsDisplay = "No upcoming events to display, please check back soon.";});
            }
            else
            {
                $scope.$apply(function(scope){scope.noEventsDisplay = "";});
            }
            $scope.$apply(function(scope){scope.events = validEvents;});

            //$('.event_list').html(eb.utils.eventList( response, eb.utils.eventListRow ));
        });
    });
}
shaunhusain
  • 19,630
  • 4
  • 38
  • 51
  • where is the start_date coming from? User input? – Axel Amthor May 30 '13 at 18:42
  • Basically yes, the EventBrite site has a form the user fills in, I request a list of all events created by a particular "organizer" and this is what it returns, I have no control of the server response... unfortunately I'm also having trouble finding the values possible for timezone_offset. – shaunhusain May 30 '13 at 18:44

1 Answers1

2

If you want a great cross-browser solution without doing it all yourself, try moment.js:

// you can define a particular format to use when parsing
var format = 'YYYY-MM-DD HH:mm:ss [GMT]ZZ';

// then just pass in your input
var m = moment(start_date + ' ' + timezone_offset, format);

// for example:
var m = moment('2013-04-27 19:00:00 GMT-0500', format);
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • I saw this mentioned in another SO post but someone had responded that it didn't work with timezones... perhaps an update since then? I'll give it a shot. – shaunhusain May 30 '13 at 19:54
  • The issue is that *JavaScript* isn't multi-timezone aware. It will pick up the offset, but on display it will adjust to whatever offset the user's local timezone demands. So for me, I'm in Arizona (-0700), the above input will be accepted, but then outputted as 17:00 instead of 19:00. Both values correspond to the same moment in time. Underneath, JS is always storing the value at UTC. – Matt Johnson-Pint May 30 '13 at 19:58
  • BTW - moment.js is doing something about that for their upcoming 2.1.0 release. See issues [611](https://github.com/timrwood/moment/issues/611) and [671](https://github.com/timrwood/moment/pull/671). – Matt Johnson-Pint May 30 '13 at 20:00
  • Alright thanks for the info Mr. Johnson... I have one more side question, if switching to this since it "wraps" Date does that mean I can still use getTime() to determine if one date is before another, or do you recommend using some moment method like moment#difference? – shaunhusain May 30 '13 at 20:01
  • You can just compare them directly: `m1 > m2`. Or you can use `m1.isBefore(m2)` or `m1.isAfter(m2)`. You can also use `.valueOf()` as an equivalent to `.getTime()`, or you can get at the underlying `Date` by using `m.toDate()`, and thus `m.toDate().getTime()`. All will work. – Matt Johnson-Pint May 30 '13 at 20:11
  • Thank *you* for just now pushing me to 10k rep. :) – Matt Johnson-Pint May 30 '13 at 20:16
  • No problem I saw that but the answer worked out well too so you didn't get the points for free :) Keep up the good work. – shaunhusain May 30 '13 at 20:23
  • @MattJohnson I don't understand why that is an 'issue'. That seems correct to me? When you are in arizona, you don't want to know what time the event will start in another timezone. You want to know what time it will be where you are. – hofnarwillie Jul 08 '14 at 16:29