Convert date string to date object? - javascript

Can someone help me:
I need to create the following.
Sunday 4 October 08.30 - 10.30 CET
Underneath this tough, I need to be able to display the local timezone??
Can someone please advise me on the best approach and can I do this with moment.js?
Thanks,

You will first need to include moment-timezone to figure out what "CET" means. Standard moment does not know how to convert named timezones to offsets.
Now, you need to use a regular expression to parse the meaningful pieces of information from your date range.
Once you have pulled out the information, reconstruct the pieces into a start and end date string.
Parse the date strings relative to the time zone.
I displayed the moment date objects in ISO 8601 format, so they will be in GMT (2 hours behind CET).
const grammar = /^(\w+) (\d+) (\w+) (\d+\.\d+) - (\d+\.\d+) (\w+)$/;
const inputFormat = 'dddd D MMMM HH.mm'
const input = 'Sunday 4 October 08.30 - 10.30 CET'
const m = input.match(grammar);
const startDateInput = `${m[1]} ${m[2]} ${m[3]} ${m[4]}`;
const endDateInput = `${m[1]} ${m[2]} ${m[3]} ${m[5]}`;
const timezone = m[6];
console.log(`Input (Start Date) : ${startDateInput}`);
console.log(`Input (End Date) : ${endDateInput}`);
const startDate = moment.tz(startDateInput, inputFormat, timezone);
const endDate = moment.tz(endDateInput, inputFormat, timezone);
console.log(`Output (Start Date) : ${startDate.toISOString()}`);
console.log(`Output (End Date) : ${endDate.toISOString()}`);
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.31/moment-timezone-with-data.min.js"></script>

I am not sure your exact question. You can use JavaScript Date Class.
//This will return time, "Mon Aug 10 2020 19:46:31 GMT+0530 (India Standard Time)"
const timeZone = /\((.*)\)/.exec(new Date().toString())[1];
// Here you can calculate offset hours
const offsetHours = new Date().getTimezoneOffset() / 60;
//This is the best way, beacuse sometimes offsethours might be wrong due to daylight saving rules
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)
And there are different ways to format a string and for other calculation.
Hope this will solve your problem.

Related

Convert a string in date (so formatted: month day, year hh:mm:ss)

I know there are tons of questions about date formatting, but I'm stuck with a conversion.
I have a string so formatted: mag 11, 2021 2:31:00 pm ("mag" is the abbreviation of May in italian).
I want to convert it in date so I can change it to the format DD/MM/YYYY HH:MM:ss (in this case "11/05/2021 14:31").
I tried to use the new Date or Date.parse functions, but in console it returns me the error 'Invalid date'.
Here's what I tried:
let a = "mag 11, 2021 2:31:00 pm";
let b = new Date(a);
console.log(b);
console output -----> Invalid Date
let a = "mag 11, 2021 2:31:00 pm";
let b = Date.parse(a);
console.log(b);
console output -----> NaN
Any idea? Thx
This question has been answered many times before, the following is for this specific case.
A Date object isn't required, the timestamp can be split into its parts, the month name converted to a number then the parts reformatted, e.g.
/*
mag 11, 2021 2:31:00 pm => DD/MM/YYYY HH:MM:ss
e.g. 11/05/2021 14:31
*/
function reformatDate(date) {
let z = n => ('0'+n).slice(-2);
let months = [,'gen','feb','mar','apr','mag','giu',
'lug','ago','set','ott','nov','dic'];
let [M,D,Y,h,m,s,ap] = date.toLowerCase().split(/\W+/);
h = h%12 + (ap == 'am'? 0 : 12);
M = months.indexOf(M);
return `${z(D)}/${z(M)}/${Y} ${z(h)}:${m}`;
}
console.log(reformatDate('mag 11, 2021 2:31:00 pm'));
In the OP, the format tokens include seconds but the example doesn't. Adding seconds to the above output if required should be easy.
The above can be modified to build the month names array based on a specific language, but then language to use would need to be passed to the function too.
If a library is used to parse the string, the language and format must be specified for the parser (e.g. date-fns allows setting the parse and format language), then the language and format of the output. So unless other date manipulation is required, a library may be more trouble than it's worth.
let now = new Date();
var dateString = moment(now).format('YYYY-MM-DD');
console.log(dateString) // Output: 2020-07-21
var dateStringWithTime = moment(now).format('YYYY-MM-DD HH:MM:SS');
console.log(dateStringWithTime) // Output: 2020-07-21 07:24:06
You can check here for all details of dateTime for Javascript

How to get date range from week number with Luxon

I'm searching a way to get date range from week number with Luxon to replace my 'moment' code.
Today I'm using this code:
m = moment(yearNumber + "-W" + weekNumber);
dateFromStr = moment(m.startOf('week')).add(1, 'day'); // To get Monday 00:00:00
dateToStr = moment(m.endOf('week')).add(1, 'day'); // To get Sunday 23:59:59
I found a way to do that from a month number with 'DateTime.fromObject()' but that's doesn't work with 'week'. So I don't find the best way to do that from a week number :(
Thank's in advance.
You can use DateTime.fromObject that:
Create a DateTime from a JavaScript object with keys like 'year' and 'hour' with reasonable defaults.
passing weekYear (an ISO week year) and weekNumber (an ISO week number, between 1 and 52 or 53, depending on the year) in the input object.
Here an live example:
const DateTime = luxon.DateTime;
const yearNumber = 2020;
const weekNumber = 3;
const dt = DateTime.fromObject({
weekYear: yearNumber,
weekNumber: weekNumber
});
const dateFromStr = dt.startOf('week');
console.log(dateFromStr.toISO()); // last Monday at 00:00:00
const dateToStr = dt.endOf('week');
console.log(dateToStr.toISO()); // next Sunday at 23:59:59
<script src="https://cdn.jsdelivr.net/npm/luxon#1.26.0/build/global/luxon.js"></script>
You can also use DateTime.fromISO passing ISO compliant format such as YYYY-Www (see more on here). Please note that week number should be two digits.

Time Zone in timeStamp param to Date constructor leads to 'invalid date' error

While trying to create date feeding a timeStamp to the Date() constructor (snippet below) - the first call works but the second call throws ('invalid date') error whenever a time zone is specified - how to correct this?
var date1 = new Date('Dec 17, 1995 03:24:00 AM EST'); //<---- THIS WORKS!!!
console.log(date1)
// Sun Dec 17 1995 03:24:00 GMT...
var date2 = new Date('1995-12-17T03:24:00 EST'); //<---- THIS DOES NOT WORK!!!
console.log(date2)
Output:
> Sun Dec 17 1995 13:54:00 GMT+0530 (India Standard Time)
> Invalid Date
> false
> NaN
This is not a duplication question as initialization from timeStamp fed to constructor is requested as against the suggested duplicate question.
You are providing the wrong format in the argument.
new Date('1995-12-17T03:24:00 EST');
What's wrong
The format you are provideing in date constructor is standard called as ISO_8601. According to standard you can not provide timezone offset like you did.
Correct way
If the time being described is one hour ahead of UTC (such as the time in Berlin during the winter), the zone designator would be "+01:00";
new Date('1995-12-17T03:24:00+01:00');
If the time being described is one hour behind of UTC, the zone designator would be "+01:00";
new Date('1995-12-17T03:24:00-01:00');
Following all refer to same time "18:30Z", "22:30+04", "1130−0700", and "15:00−03:30".
This code doesn't solve the problem for directly timestamping time-zones but provides an alternative to supporting preferred time-zones as well creating js acceptable time-stamps converting numerical month to month name dynamically. This is just crude solution open to suggestions.
function getTZId(zone) {
var retId = zone;
if (zone) {
//placeholder to maintain / add new zone id patterns
//a word of caution: some timezones are not supported so offset will be required
var zoneIds = {
'EST':[/ET/,/EST/,/EAST/,/OTT/],
'UTC+5:30':[/IST/,/IND/,/GURG/],
'CST':[/CENTR/,/NA/],
'UTC':[/UTC/,/GMT/,/ZULU/,/Z/,/GREEN/]
}
//default zone id
var defZnId = 'UTC';
var fnd = _.findIndex (
Object.keys( zoneIds ),
//lookup all zone id's for a match among respective zone patterns till first matching zone id is found
znId => {
return (
_.findIndex (
zoneIds[znId],
//match each zone pattern for this zone id till the first match is found
znPtrn=>{
return znPtrn.test( zone.toUpperCase() )
}
) !== -1
)
}
);
//return zone id if matching zone id found else return default zone id: 'UTC'
retId = (fnd!==-1?Object.keys( zoneIds )[fnd]:defZnId);
}
return retId;
}
var yr = "2018", mn = "2", dy = "28", hr = "14", min = "05";
var timezone = "EST";
//get date components for current timezone like month names etc
var tmpDt = (new Date(`${yr}-${mn}-${dy}T${hr}:${min}`)).toDateString().match(/^([A-Za-z]+)\s+([A-Za-z]+)\s+(\d+)\s+(\d+)$/i);
//use above code to create appropriate time stamp
return (new Date(`${tmpDt[2]} ${tmpDt[3]}, ${yr} ${hr}:${min}:00 ${getTZId(tmZoneStr)}`));

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.

How to the get the beginning of day of a date in javascript -- factoring in timezone

I am struggling to find out the beginning of day factoring in timezones in javascript. Consider the following:
var raw_time = new Date(this.created_at);
var offset_time = new Date(raw_hour.getTime() + time_zone_offset_in_ms);
// This resets timezone to server timezone
var offset_day = new Date(offset_time.setHours(0,0,0,0))
// always returns 2011-12-08 05:00:00 UTC, no matter what the offset was!
// This has the same issue:
var another_approach_offset_day = new Date(offset_time.getFullYear(),offset_time.getMonth(),offset_time.getHours())
I expect when i pass a Pacific Timezone offset, to get: 2011-12-08 08:00:00 UTC and so on.
What is the correct way to achieve this?
I think that part of the issue is that setHours method sets the hour (from 0 to 23), according to local time.
Also note that I am using javascript embedded in mongo, so I am unable to use any additional libraries.
Thanks!
Jeez, so this was really hard for me, but here is the final solution that I came up with the following solution. The trick was I need to use setHours or SetUTCHours to get the beginning of a day -- the only choices I have are system time and UTC. So I get the beginning of a UTC day, then add back the offset!
// Goal is given a time and a timezone, find the beginning of day
function(timestamp,selected_timezone_offset) {
var raw_time = new Date(timestamp)
var offset_time = new Date(raw_time.getTime() + selected_timezone_offset);
offset_time.setUTCHours(0,0,0,0);
var beginning_of_day = new Date(offset_time.getTime() - selected_timezone_offset);
return beginning_of_day;
}
In JavaScript all dates are stored as UTC. That is, the serial number returned by date.valueOf() is the number of milliseconds since 1970-01-01 00:00:00 UTC. But, when you examine a date via .toString() or .getHours(), etc., you get the value in local time. That is, the local time of the system running the script. You can get the value in UTC with methods like .toUTCString() or .getUTCHours(), etc.
So, you can't get a date in an arbitrary timezone, it's all UTC (or local). But, of course, you can get a string representation of a date in whatever timezone you like if you know the UTC offset. The easiest way would be to subtract the UTC offset from the date and call .getUTCHours() or .toUTCString() or whatever you need:
var d = new Date();
d.setMinutes(d.getMinutes() - 480); // get pacific standard time
d.toUTCString(); // returns "Fri, 9 Dec 2011 12:56:53 UTC"
Of course, you'll need to ignore that "UTC" at the end if you use .toUTCString(). You could just go:
d.toUTCString().replace(/UTC$/, "PST");
Edit: Don't worry about when timezones overlap date boundaries. If you pass setHours() a negative number, it will subtract those hours from midnight yesterday. Eg:
var d = new Date(2011, 11, 10, 15); // d represents Dec 10, 2011 at 3pm local time
d.setHours(-1); // d represents Dec 9, 2011 at 11pm local time
d.setHours(-24); // d represents Dec 8, 2011 at 12am local time
d.setHours(52); // d represents Dec 10, 2011 at 4am local time
Where does the time_zone_offset_in_ms variable you use come from? Perhaps it is unreliable, and you should be using Date's getTimezoneOffset() method. There is an example at the following URL:
http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp
If you know the date from a different date string you can do the following:
var currentDate = new Date(this.$picker.data('date'));
var today = new Date();
today.setHours(0, -currentDate.getTimezoneOffset(), 0, 0);
(based on the codebase for a project I did)
var aDate = new Date();
var startOfTheDay = new Date(aDate.getTime() - aDate.getTime() % 86400000)
Will create the beginning of the day, of the day in question
You can make use of Intl.DateTimeFormat. This is also how luxon handles timezones.
The code below can convert any date with any timezone to its beginging/end of the time.
const beginingOfDay = (options = {}) => {
const { date = new Date(), timeZone } = options;
const parts = Intl.DateTimeFormat("en-US", {
timeZone,
hourCycle: "h23",
hour: "numeric",
minute: "numeric",
second: "numeric",
}).formatToParts(date);
const hour = parseInt(parts.find((i) => i.type === "hour").value);
const minute = parseInt(parts.find((i) => i.type === "minute").value);
const second = parseInt(parts.find((i) => i.type === "second").value);
return new Date(
1000 *
Math.floor(
(date - hour * 3600000 - minute * 60000 - second * 1000) / 1000
)
);
};
const endOfDay = (...args) =>
new Date(beginingOfDay(...args).getTime() + 86399999);
const beginingOfYear = () => {};
console.log(beginingOfDay({ timeZone: "GMT" }));
console.log(endOfDay({ timeZone: "GMT" }));
console.log(beginingOfDay({ timeZone: "Asia/Tokyo" }));
console.log(endOfDay({ timeZone: "Asia/Tokyo" }));

Categories