Proper way to parse a date as UTC using date-fns - javascript

I have a log file with some timestamps
2020-12-03 08:30:00
2020-12-03 08:40:00
...
I know from the log provider's documentation that the timestamps are written in UTC (although not using ISO format)
Now I want to parse them with date-fns :
const toParse = "2020-12-03 08:40:00"
parse(toParse, 'yyyy-MM-dd HH:mm:ss', new Date()).toISOString()
And because the locale of my computer is in UTC+1 here is what I see:
> "2020-12-03T07:40:00Z"
expected:
> "2020-12-03T08:40:00Z".
Here is the hack I currently use to tell date-fns to parse as UTC :
const toParse = "2020-12-03 08:40:00"
parse(toParse + '+00', 'yyyy-MM-dd HH:mm:ss' + 'X', new Date()).toISOString()
And as expected,
> "2020-12-03T08:40:00Z".
Is there any proper way of doing this using date-fns? Looking for an equivalent to moment's moment.utc()

I don't know about "proper", but you can use zonedTimeToUtc to treat a timestamp as having any offset or timezone you like, including UTC, e.g.
// Setup
var {parse} = require('date-fns');
var {zonedTimeToUtc} = require('date-fns-tz');
// Parse an ISO 8601 timestamp recognised by date-fns
let loc = 'UTC';
let s1 = '2020-12-03 08:30:00';
let utcDate = zonedTimeToUtc(s1, loc);
// Show UTC ISO 8601 timestamp
console.log(utcDate.toISOString()); // "2020-12-03T08:30:00.000Z"
// Parse non–standard format yyyyMMdd
let s2 = '20210119';
let fIn = 'yyyyMMdd';
let d = zonedTimeToUtc(parse(s2, fIn, new Date()), loc);
console.log(d.toISOString()); // "2021-01-19T00:00:00.000Z"```
You can test it at npm.runkit.com/date-fns.

I think you are looking for parseJSON, which supports a number of formats (but does not let you specify the source format).
Converts a complete ISO date string in UTC time, the typical format for transmitting a date in JSON, to a JavaScript Date instance.
import { parseJSON } from 'date-fns';
const utcDate = parseJSON('2020-12-03 08:40:00');
// Thu Dec 03 2020 19:40:00 GMT+1100 (Australian Eastern Daylight Time)

Example of using parse and zonedTimeToUtc
it('should parse polish date', async () => {
expect.assertions(1)
const dateWithoutTime = '29 gru 2003'
const parsed = parse(dateWithoutTime, 'd LLL yyyy', new Date(), {
locale: pl,
})
const dateUTC = zonedTimeToUtc(parsed, 'UTC')
expect(dateUTC.toISOString()).toStrictEqual('2003-12-29T00:00:00.000Z')
})

Related

Covert date to epoch timestamp using Javascript

I have date in MM/DD/YYYY HH:MM AM/PM format
Example 07/27/2022 10:36 AM
I want to convert it into Epoch timestamp which is 1658898360
You can use the date.getTime method to convert it to epoch:
const date = new Date("07/27/2022 10:36 AM");
console.log(date.getTime() / 1000)
Just be sure that you (or the client) is in the same timezone you are expecting (IST in this case).
Or just add GMT+5:30 to ensure this.
const date = new Date("07/27/2022 10:36 AM GMT+5:30");
console.log(date.getTime() / 1000)
The Date object in Javascript is notoriously tricky to work with, and date parsing is sadly lacking. Simply using
const dateString = "07/27/2022 10:36 AM"
const date = new Date(dateString)
might work, but not reliably.
One option is to use the date-fns library:
import { parse, getUnixTime } from 'date-fns'
const date = parse('07/27/2022 10:36 AM', 'MM/dd/yyyy hh:mm a', new Date())
const epoch = getUnixTime(date)
You can use below sample code:
function epoch (date) {
return Date.parse(date)
}
const dateToday = new Date()
const timestamp = epoch(dateToday)
console.log( timestamp )

How to convert into Format 2016-10-19T08:00:00Z with momentjs

in a project we are using momentjs with date. And from backend we become the date in the following format: 2016-10-19T08:00:00Z (don't ask me why...)
Now we are setting a new date in frontend from some selectboxes. And I am trying to convert this in the same format:
const date = '25.03.2021';
const hour = '13';
const minute = '45'; // this 3 values come from value of selectboxes
const rawDate = moment(date).hour(hour).minute(minute);
// trying to convert to 2021-03-25T13:45:00Z
rawDate.format(); // output: 2021-03-25T13:45:00+00:00
rawDate.format('DD.MM.YYYY hh:mm:ss'); // output: 03.01.2022 08:00:00
rawDate.format('DD.MM.YYYY hh:mm:ss z'); // output: 03.01.2022 08:00:00 UTC
rawDate.format('DD.MM.YYYY hh:mm:ss Z'); // output: 03.01.2022 08:00:00 +00:00
rawDate.toISOString(); // output: 2022-01-03T08:00:00.000Z
I know I could probably just use format() or toISOString() and slice/replace the last bit. But I like to know is there a way without any string concat/manipulation?
You could use moment.utc() to ensure your date is in UTC, then use .format() with the format string DD-MM-YYYYTHH:mm:ss[Z].
I'd also suggest explicity defining the format you are parsing from in the moment() call, e.g. pass 'DD.MM.YYYY' as the second argument.
The reason the backend takes dates in this format is that it's a standardized way of formatting dates to make them machine-readable and consistent (ISO 8601)
const date = '25.03.2021';
const hour = '13';
const minute = '45';
// Raw date will be in the UTC timezone.
const rawDate = moment(date, 'DD.MM.YYYY').hour(hour).minute(minute).utc();
console.log(rawDate.format('DD-MM-YYYYTHH:mm:ss[Z]'));
<script src="https://momentjs.com/downloads/moment.js"></script>
You can try convert to UTC ..?
i.e. Do you intend to make use of a UTC date/time..?
const date = '2021-03-25';
const hour = '13';
const minute = '45'; // this 3 values come from value of selectboxes
const rawDate = moment(date).hour(hour).minute(minute);
const utc = moment.utc(rawDate);
console.log(rawDate.format('DD.MM.YYYY hh:mm:ss'));
console.log(utc.format()); //2021-03-25T11:45:00Z

Check if an iso string date is same or before an hour using moment

I've a string date in ISO format and a string in format HH:mm.
I want to know if the hour of the string ISO date is same or before the string in format HH:mm.
Example:
const isoDateString = '2021-09-28T07:30:00Z' // UTC
const hour = '07:30' // not UTC
-> result true
---
const isoDateString = '2021-09-28T07:30:00Z' // UTC
const hour = '08:30' // not UTC
-> result false
I'm using moment and this is my code:
const TIME_FORMAT = 'HH:mm'
const isoDateString = '2021-09-28T09:30:00Z'
const hour = '07:30'
const isHourSameOrBeforeIsoString = moment(
moment(isoDateString).format(TIME_FORMAT),
).isSameOrBefore(moment(hour, TIME_FORMAT));
console.log(isHourSameOrBeforeIsoString)
It doesn't work. It returns false in both cases. Why?
Use moment.utc() when constructing your iso date string because you should handle that as in UTC.
I also added TIME_FORMAT inside moment constructor of formatted iso date string.
const TIME_FORMAT = 'HH:mm'
const isoDateString = '2021-09-28T09:30:00Z'
const hour = '07:30'
const isHourSameOrBeforeIsoString = moment(
moment.utc(isoDateString).format(TIME_FORMAT), TIME_FORMAT
).isSameOrBefore(moment(hour, TIME_FORMAT));
console.log(isHourSameOrBeforeIsoString)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
Here is a more reasonable way to check in my opinion:
The logic you had was correct, but the reason it is returning false is because your isoDateString is returning 8:30 and the hour you are comparing it to is 7:30, like Krzysztof mentioned in their comment, it could be a time zone issue:
var format = 'hh:mm'
// var time = moment() gives you current time. no format required.
var time = moment('2021-09-28T09:30:00Z',format),
testTime = moment('07:30', format);
console.log(moment(time).format(format));
console.log(moment(testTime).format(format));
if (time.isSameOrBefore(testTime)) {
console.log('is before')
}
if(time.isSameOrAfter(testTime)){
console.log('is after')
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" referrerpolicy="no-referrer"></script>

Date in CET timezone to user's timezone

I have a list of list of string dates like this: '17/12/2017 19:34'. They are CET dates.
How can I transform it to the user's browser date?
I'm doing this:
const tzGuess = moment.tz.guess()
export const toTimeZone = (time) => {
const format = 'DD/MM/YYYY HH:mm'
return moment(time, format).tz(tzGuess).format(format)
}
console.log(toTimeZone('17/12/2017 19:34', tzGuess))
but how can I say to moment that the date I'm passing at first is a CET one?
Thanks!
You can use moment.tz function for parsing time string using a given timezone (e.g. 'Europe/Madrid').
The issue is: what do you mean with CET? If your input has fixed UTC+1 offset (like Central European Time), then you can use RobG's solution. If you have to consider both CET and CEST, I think that the best soution is to use moment.tz.
Here a live code sample:
const tzGuess = moment.tz.guess()
const toTimeZone = (time) => {
const format = 'DD/MM/YYYY HH:mm'
return moment.tz(time, format, 'Europe/Madrid').tz(tzGuess).format(format)
}
console.log(toTimeZone('17/12/2017 19:34', tzGuess))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.4/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.13/moment-timezone-with-data-2012-2022.min.js"></script>
A great resource about timezone is the timezone tag info page.
Without moment.js, parse the string to a Date, treating it as UTC, then adjust for the CET offset (+0100). You can then format it using local time values for the client:
// Parse date in format DD/MM/YYYY HH:mm
// Adjust for CET timezone
function parseCET(s) {
var b = s.split(/\D/);
// Subtract 1 from month and hour
var d = new Date(Date.UTC(b[2], b[1]-1, b[0], b[3]-1, b[4]));
return d;
}
var s = '17/12/2017 19:34';
console.log(parseCET(s).toString());
However, if the time needs to observe daylight saving (CEST) for the source time stamp, you'll need to account for that.

Time not getting converted to local time properly via moment.js

11-06-2015 12:44:30
My datetime has the above format however it isn't getting converted to Local Time it gives me the month as November instead.
var check = moment('#Model.Invoice.InvoiceDate').format('YYYY-MM-DD HH:mm:ss');
var localTime = moment.utc(check).toDate();
localTime = moment(localTime).format('YYYY-MM-DD HH:mm:ss');
console.log(localTime);
White saving i am using DateTime.UTCNow function of C# and while getting the data i am using the following code.
Code:
var formatDate = new Date('#Model.Invoice.InvoiceDate.ToLocalTime()');
console.log(formatDate);
formatDate = moment.utc(formatDate).toDate();
console.log(formatDate);
var dateTime = moment(formatDate).format('lll');
console.log(dateTime);
Example of what is happening:
var formatDate = new Date('Sat Jun 13 2015 13:00:11 GMT+0530 (India Standard Time)');
console.log(formatDate);
formatDate = moment.utc(formatDate).toDate();
console.log(formatDate);
var dateTime = moment(formatDate).format('lll');
console.log(dateTime);
You can print an UTC ISO 8601 date for moment with ToString("s") but it will lack the Z, so you need to add it yourself.
var localTime = moment('#String.concat(Model.Invoice.InvoiceDate.ToString("s"), "Z")').format('lll');
Or by adding the Z on client side :
var localTime = moment('#Model.Invoice.InvoiceDate.ToString("s")' + 'Z').format('lll');
Try this
var check = moment('11-06-2015 12:44:30', 'DD-MM-YYYY HH:mm:ss')
.format('YYYY-MM-DD HH:mm:ss');
or in your case this
var check = moment('#Model.Invoice.InvoiceDate', 'DD-MM-YYYY HH:mm:ss')
.format('YYYY-MM-DD HH:mm:ss');
instead of
var check = moment('#Model.Invoice.InvoiceDate')
.format('YYYY-MM-DD HH:mm:ss');
While giving moments a date string you need to specify which part is what.

Categories