Skip to content

Instantly share code, notes, and snippets.

@DaneWeber
Created September 24, 2019 15:45
Show Gist options
  • Save DaneWeber/efb476bd8972aec3a37a338b8a3ecd88 to your computer and use it in GitHub Desktop.
Save DaneWeber/efb476bd8972aec3a37a338b8a3ecd88 to your computer and use it in GitHub Desktop.
ISO8601 date & time with offset for Javascript
Date.prototype.toJSON = function () {
const tzOffset = 0 - this.getTimezoneOffset(); // Javascript is backwards from ISO8601
const sign = tzOffset >= 0 ? '+' : '-';
const timezoneOffsetInHours = Math.abs(Math.floor(tzOffset / 60));
const leadingHourZero = timezoneOffsetInHours < 10 ? '0' : '';
const timezoneOffsetMinuteRemainder = Math.abs(Math.floor(tzOffset % 60));
const leadingMinuteZero = timezoneOffsetMinuteRemainder < 10 ? '0' : '';
const offset = sign + leadingHourZero + timezoneOffsetInHours + ':' + leadingMinuteZero + timezoneOffsetMinuteRemainder;
const fakeDate = new Date(Date.UTC(this.getFullYear(), this.getMonth(),
this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds()));
const iso = fakeDate.toISOString().substring(0,19);
return iso + offset;
};
import "./dateToJSON";
// This spec file should be exercised in various timezones. Set the timezone in the container with
// docker exec -it -e TZ=Pacific/Chatham cmd
// Or interactively with commands like the following:
// echo "Pacific/Niue" > /etc/timezone
// dpkg-reconfigure tzdata
// date
describe('Date Prototype', () => {
describe('toJSON', () => {
const localNow = new Date();
const localNowToJSON = localNow.toJSON();
it('Date().toJSON() overrides the usual JSON.stringify() behavior (which is used by Axios for posting to API endpoints)', () => {
const expectedResult = '"' + localNowToJSON + '"';
const result = JSON.stringify(localNow);
expect(result).toEqual(expectedResult);
});
it('new Date().toJSON() produces a string', () => {
// act
const result = new Date().toJSON();
// assert
expect(result).toEqual(expect.any(String));
});
it('produces an ISO8601 timestamp with offset', () => {
// arrange
const now = new Date();
// 2000-01-24T02:34:56-10:00
const iso8601pattern = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}/;
// act
const result = now.toJSON();
// assert
expect(result).toMatch(iso8601pattern);
});
it('matches the local year', () => {
// arrange
const expectedResult = localNow.getFullYear();
// act
const result = parseInt(localNowToJSON.substring(0,4), 10);
// assert
expect(result).toEqual(expectedResult);
});
it('matches the local month', () => {
// arrange
const expectedResult = localNow.getMonth() + 1;
// act
const result = parseInt(localNowToJSON.substring(5,7), 10);
// assert
expect(result).toEqual(expectedResult);
});
it('matches the local date', () => {
// arrange
const expectedResult = localNow.getDate();
// act
const result = parseInt(localNowToJSON.substring(8,10), 10);
// assert
expect(result).toEqual(expectedResult);
});
it('matches the local hour', () => {
// arrange
const expectedResult = localNow.getHours();
// act
const result = parseInt(localNowToJSON.substring(11,13), 10);
// assert
expect(result).toEqual(expectedResult);
});
it('matches the local minutes', () => {
// arrange
const expectedResult = localNow.getMinutes();
// act
const result = parseInt(localNowToJSON.substring(14,16), 10);
// assert
expect(result).toEqual(expectedResult);
});
it('matches the local seconds', () => {
// arrange
const expectedResult = localNow.getSeconds();
// act
const result = parseInt(localNowToJSON.substring(17,19), 10);
// assert
expect(result).toEqual(expectedResult);
});
it('includes the correct local UTC offset sign', () => {
// arrange
const expectedResult = 0 - localNow.getTimezoneOffset() >= 0 ? '+' : '-';
// act
const result = localNowToJSON.substring(19,20);
// assert
expect(result).toEqual(expectedResult);
});
it('includes the local UTC offset hours', () => {
// arrange
const expectedResult = Math.floor(Math.abs(localNow.getTimezoneOffset() / 60));
// act
const result = parseInt(localNowToJSON.substring(20,22), 10);
// assert
expect(result).toEqual(expectedResult);
});
it('includes the local UTC offset minutes', () => {
// arrange
const expectedResult = Math.abs(localNow.getTimezoneOffset() % 60);
// act
const result = parseInt(localNowToJSON.substring(23,25), 10);
// assert
expect(result).toEqual(expectedResult);
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment