Generate an RFC 3339 timestamp similar to Google Tasks API?
Asked Answered
I

8

55

I am in the process of building an app that syncs with Google Tasks. As part part of the syncing, I want to compare the local task and the API task, and see which one has been changed more recently.

Each task from Google's API contains an updated property, which looks like this:

2011-08-30T13:22:53.108Z

Now I would like to generate a timestamp similar to that, so that every time I update a task on my app it sets a new updated value. To generate the RFC 3339 timestamp I am using - http://cbas.pandion.im/2009/10/generating-rfc-3339-timestamps-in.html which generates something like this:

2011-08-30T09:30:16.768-04:00

The issue is, the API date is always coming back as "greater" than the local date, even when the local date is newer. I'm guessing it has something to do with the different formatting between the two.

Here are two dates, the top is from the Google Tasks API (from about 10 minutes ago), and the bottom one was generated locally a minute ago. When compared which is greater, it's telling me the top one is.

2011-08-30T13:22:53.108Z
2011-08-30T09:41:00.735-04:00

Is my formatting wrong? What I am doing wrong here? Any help on this is really appreciated.

Interoffice answered 30/8, 2011 at 13:48 Comment(0)
P
52

The formatting is ISO so new Date().toISOString() will give you that form. Which as I'm reading might need to be shimmed:

/* use a function for the exact format desired... */
function ISODateString(d){
 function pad(n){return n<10 ? '0'+n : n}
 return d.getUTCFullYear()+'-'
      + pad(d.getUTCMonth()+1)+'-'
      + pad(d.getUTCDate())+'T'
      + pad(d.getUTCHours())+':'
      + pad(d.getUTCMinutes())+':'
      + pad(d.getUTCSeconds())+'Z'}

var d = new Date();
print(ISODateString(d)); // prints something like 2009-09-28T19:03:12Z

Source: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date

Panto answered 30/8, 2011 at 13:51 Comment(2)
Wow thanks. I must have gotten confused cause google says that want a "RFC 3339 timestamp" to pass in as an updatedMin argument when pulling tasks.Interoffice
RFC 3339 is a narrow subset of ISO 8601. Read the RFC for excellent explanations why defining a subset was helpful. Almost nobody uses or implements all the options of ISO 8601, so when people say "ISO format" they de-facto usually mean a single specific format, frequently the one RFC 3339 focuses on.Rafaelarafaelia
M
87

It seems like a lot of complicated answers have been given, but this works just fine, does it not?

new Date().toISOString()
Mirna answered 16/9, 2016 at 10:7 Comment(4)
toISOString() gives a representation that has the day and month digits inverted wrt the RFC3339 standard.Mcnamee
It includes fractions of seconds: 2019-03-27T15:12:47.921Z . You'll need to cut them off.Birkner
@LucaDiLiello RFC3339 says YYYY-MM-DD, that's what toISOString() outputs.Mirna
@IvanYarych The fractions of a second are valid ISO8601/RFC3339 format, it's just rarely used. Anything that parses according to the spec should just work.Mirna
P
52

The formatting is ISO so new Date().toISOString() will give you that form. Which as I'm reading might need to be shimmed:

/* use a function for the exact format desired... */
function ISODateString(d){
 function pad(n){return n<10 ? '0'+n : n}
 return d.getUTCFullYear()+'-'
      + pad(d.getUTCMonth()+1)+'-'
      + pad(d.getUTCDate())+'T'
      + pad(d.getUTCHours())+':'
      + pad(d.getUTCMinutes())+':'
      + pad(d.getUTCSeconds())+'Z'}

var d = new Date();
print(ISODateString(d)); // prints something like 2009-09-28T19:03:12Z

Source: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date

Panto answered 30/8, 2011 at 13:51 Comment(2)
Wow thanks. I must have gotten confused cause google says that want a "RFC 3339 timestamp" to pass in as an updatedMin argument when pulling tasks.Interoffice
RFC 3339 is a narrow subset of ISO 8601. Read the RFC for excellent explanations why defining a subset was helpful. Almost nobody uses or implements all the options of ISO 8601, so when people say "ISO format" they de-facto usually mean a single specific format, frequently the one RFC 3339 focuses on.Rafaelarafaelia
N
12

I've found the moment.js library nice for working with time in javascript. moment().format() yields a timestamp in the format expected by the Google API for a datetime. Or, to not depend on the default format being correct for your application,

moment().format("YYYY-MM-DDTHH:mm:ssZ")

All the string options (including fractional seconds if that's what you need): http://momentjs.com/docs/#/displaying/format/

Nary answered 25/9, 2013 at 3:17 Comment(3)
the Z char is meaning timezone, you can't use it directlySoilasoilage
moment().toISOString() // 2013-02-04T22:44:30.652ZSoilasoilage
Use of a third party library should always be a last resort if there is something available in the language itself.Mirna
R
6

Using date-fns, this is very elegant:

import { formatRFC3339 } from 'date-fns'

const result = formatRFC3339(new Date(2019, 8, 18, 19, 0, 52))
//=> '2019-09-18T19:00:52Z'

Source:

Rajkot answered 21/6, 2021 at 18:19 Comment(1)
works fine for me, it is documented here date-fns.org/v2.23.0/docs/formatRFC3339Schatz
S
3

If you are using Google Script, another option is to use Utilities.formatDate URL below:

https://developers.google.com/apps-script/reference/utilities/utilities#formatDate(Date,String,String)

Sample code from above URL:

// This formats the date as Greenwich Mean Time in the format
// year-month-dateThour-minute-second.
var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd'T'HH:mm:ss'Z'");
Sarnen answered 18/10, 2013 at 19:54 Comment(0)
H
1

try this:

Date.prototype.setRFC3339 = function(dString) {
    var utcOffset, offsetSplitChar;
    var offsetMultiplier = 1;
    var dateTime = dString.split("T");
    var date = dateTime[0].split("-");
    var time = dateTime[1].split(":");
    var offsetField = time[time.length - 1];
    var offsetString;
    offsetFieldIdentifier = offsetField.charAt(offsetField.length - 1);
    if (offsetFieldIdentifier == "Z") {
        utcOffset = 0;
        time[time.length - 1] = offsetField.substr(0, offsetField.length - 2);
    } else {
        if (offsetField[offsetField.length - 1].indexOf("+") != -1) {
            offsetSplitChar = "+";
            offsetMultiplier = 1;
        } else {
            offsetSplitChar = "-";
            offsetMultiplier = -1;
        }
        offsetString = offsetField.split(offsetSplitChar);
        time[time.length - 1] == offsetString[0];
        offsetString = offsetString[1].split(":");
        utcOffset = (offsetString[0] * 60) + offsetString[1];
        utcOffset = utcOffset * 60 * 1000;
    }

    this.setTime(Date.UTC(date[0], date[1] - 1, date[2], time[0], time[1], time[2]) + (utcOffset * offsetMultiplier));
    return this;
};

source: http://blog.toppingdesign.com/2009/08/13/fast-rfc-3339-date-processing-in-javascript/

Havoc answered 30/8, 2011 at 13:51 Comment(0)
W
1

The Z behind the first date indicates it's UTC (Zulu) time, without the Z it will use the local (computer) time, which could be several time zones off.

See: http://en.wikipedia.org/wiki/UTC

Wastrel answered 30/8, 2011 at 13:54 Comment(0)
S
-5

It looks more pretty: new Date().toISOString().split('.')[0] + 'Z'

Satinet answered 20/12, 2018 at 23:28 Comment(1)
They asked for RFC output, not some ambiguous definition of "pretty" output; so that's off topic.Mirna

© 2022 - 2024 — McMap. All rights reserved.