Change moment timezone not reflecting to .toDate() - javascript

Ngx Bootstrap Datepicker returns a JS Date object.
I have a custom Time picker that returns a string formatted as HH:mm.
What I need to do right now is to create a JS Date object with the selected Date, selected Time and a specific TimeZone.
I'm trying to use moment (cause we use that for dates in the whole application) but I'm having not expected behaviours.
I'm trying to:
const specificMoment = moment.tz(date, timeZone); // date is the Ngx Bootstrap selected date
specificMoment.set('hour', +time.split(':')[0]); // time is HH:mm string
specificMoment.set('minute', +time.split(':')[1]);
return specificMoment.toDate
*timeZone changes according to the user, not due to it's browser, it's an attribute of the user, so I can't set moment.tz.setDefault(...);.
What I'm facing is that .toDate is returning my current timeZone, event though it appears my different timeZone inside the moment object.
Why is it working like this and what would be a working implementation for what I need?
Ps: console.log(specificMoment.format()); returns wrong timeZone as well 2018-12-20T23:00:30-02:00.
EDIT
Turns out using const specificMoment = moment(date).tz(timeZone); and then return specificMoment.toDate() "works". It returns a Date object with 2018-12-21T05:00:00.323-0200, which is the date with specified timezone (GMT -8:00) but displayed on my current timezone (GMT -2:00).
The data is stored on my DB correctly.
Can someone explain why?
Thx.

It looks like you haven't setup moment-timezone with any data about the timezone to use.
Check out this link on Data Loading in momentjs.
I've created a JS Bin for your example that shows how to use Data Loading. Check it out here.
e.g.
moment.tz.add([
'America/Los_Angeles|PST PDT|80 70|0101|1Lzm0 1zb0 Op0',
'America/New_York|EST EDT|50 40|0101|1Lz50 1zb0 Op0'
]);

Related

Bootstrap datepicker setStartDate not working properly?

I am using Bootstrap datepicker and on selecting different values from a list its startdate is changing. It is working fine if I set the startdate 2013 from 2008 but it doesn't work if a select start date 2008 and currently its 2013.
What could be the reason here?
$('#datepicker').datepicker('setStartDate', updatedDate);
This line I am executing whenever I select different startDate.
Really need to know what updatedDate value is.
However, if you read the docs for the dtepicker the value passed in must be a string that is understandable by format
https://bootstrap-datepicker.readthedocs.io/en/latest/methods.html#setstartdate
https://bootstrap-datepicker.readthedocs.io/en/latest/options.html#startdate
Date or String. Default: Beginning of time
The earliest date that may be selected; all earlier dates will be
disabled.
Date should be in local timezone. String must be parsable with format.
So what you pass in as the format option must match the format of your start date. If you do not set the format optin, the default is "mm/dd/yyyy"
Without seeing code, I can only hypothesize; try calling [...].datepicker('update', 'date_string'); on the object to force an update on the control.

Show the date according to it's created timezone - JavaScript

Suppose there's an event created in country A,
and the timeString is "2015-08-27T16:00:32+02:00"
A person (me) wants to see the event's time but not according to my local gmt, lets say mine is +05:00.. I want to show the user the creator's timezone i.e.
2015-08-27T16:00:32+02:00
In short, the time shown should be 4:00PM (according to +02:00) , not 7:00PM (according to +05:00)
is there any solution using the native javascript Date object or moment.js?
You should save in your database the date and the timezone of the creator. Then when you have to display them, you can do something like:
$(document).ready(function () {
moment.tz.add('America/Los_Angeles|PST PDT|80 70|0101|1Lzm0 1zb0 Op0');
var date = moment('2015-08-27T16:00:32+02:00'); // Get date from db
$('#date').html(date.format('LLLL')); // Display date using the browser's timezone
var timezone = 'America/Los_Angeles';// Get timezone from db
$('#newDate').html(date.clone().tz(timezone).format('LLLL')); // Clone the date, set the new timezone and display
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.4.0/moment-timezone.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="date"></pre>
<pre id="newDate"></pre>
In this example, you get the date from the database and you display it in the upper box. As always, moment tries to use your browser's timezone to display the date.
Then you get the timezone from the database, you set the new timezone and you can see that the dates changes in the lower box.
Obviously this example works only if you are not in the America/Los_Angeles timezone. In this case you should get two equal strings, which is actually the correct behavior but it wouldn't allow you to see moment_timezone in action.

momentjs: how to get the date in a specific timezone

In a nutshell I want moment to respect server's timezone. I've set my machine's timezone to Alaska but I'm passing a Brisbane timezone string to moment. Now I need moment.toDate to return a date instance in the same timezone as the one I pass in the moment constructor; e.g.
m = moment("2016-11-20T08:00:00+10:00")
m.format() // "2016-11-20T08:00:00+10:00"
m.toDate() // Sat Nov 19 2016 13:00:00 GMT-0900 (AKST)
I want to get a Date instance from moment that's in the input timezone; e.g. somehow get toDate to return Sun Nov 20 2016 08:00:00 GMT+1000 (AEST).
FWIW I have tried the same code with and without moment.tz.setDefault and while it correctly changes the format result, toDate always uses the machine's timezone!
Update
The reason I need this behaviour is that some JavaScript libraries and controls don't understand moment and only work with Date and the time/date gets skewed when presented back by them. One example, the one I'm currently dealing with, is jQuery UI date picker control. I want the date picker to show the current date as it's on the server (or on a specific timezone).
Thanks in advance.
The Date object represents the time in UTC internally, and can only use the time zone of the machine its running on when projected.
There's absolutely no way to produce a Date object that uses an arbitrary time zone. Any examples you may come across that try to manipulate the Date object (such by adding or subtracting time zone offsets) are fundamentally flawed.
Moment itself has great time zone support, including the moment-timezone extension for working with named time zones instead of just time zone offsets. But once you go back to a Date object - you're back at the mercy of the behavior of that object.
Sorry, but there's no way to achieve what you are asking. Perhaps you could elaborate as to why you wanted to do this, and I could recommend a workaround.
Update: With regards to your update, usually there is a mechanism for getting the value from a date picker as text, rather than as a date object. With the example of the jQuery UI date picker control, the onSelect event gives it to you as text already, or you can simply call .val() instead of .datepicker('getDate') to get the text out of the field. Once you have a textual value, you can then parse it with moment however you like.
Similarly, when setting the value, you don't necessarily need a Date object. You could just set the value of the textbox as a string, or you can pass a string to the setDate function.
In most cases, you won't have to go through a Date object. But if for some reason you do, then you'll need to artificially construct one with something crazy like:
var d = new Date(m.format('YYYY/MM/DD'));
Normally, I'd be against that - but if it's just there to get the pass a value to a UI control, then it's probably ok.
This will get you a moment in the same timezone as the moment string, but toDate is always in the local timezone.
d = "2016-11-20T08:00:00+10:00"
m = moment(d).utcOffset(d)
m.format()
m.toDate()

How to send AngularStrap datepicker value without timezone?

I'm wondering if it's possible to use AngularStrap's datepicker without it keeping the user's locale's timezone information. In our application we want to handle Contract objects that have an expiration date.
When adding or editing the contract object, there is a datepicker field for selecting the date. The following thing happens:
The user selects the date (e.g. 2013-10-24)
Angular binds the javascript date object to the ng-model field
The binded date object is in the user's timezone (e.g. GMT+3)
The user submits the form
The date gets sent to the server using Angular's $http service
In step 5 the date is converted to UTC format. The selected date was GMT+3 2013-10-24 at midnight, but the UTC conversion changes the date to 2013-10-23 at 9pm.
How could we prevent the conversion, or use UTC dates during the whole process? We don't want the contract's date to change based on the user's local timezone. Instead, we want the date to be always 2013-10-24, no matter what timezone.
Our current solution was to make small changes to the AngularStrap library so that the date won't change when sent to the server.
If we could get the user's selected timezone in the server, we could make another conversion there, but the server doesn't have that information.
All ideas are appreciated!
The issue isn't AngularStrap. Its just how javascript dates work and how JSON formats them for transmission. When you turn a javascript date object into a JSON string, it formats the string as UTC.
For example, I'm in Utah and it is now 07:41 on 2013-10-24. If I create a new javascript date and print it to the console it will say:
Thu Oct 24 2013 07:41:19 GMT-0600 (MDT)
If I stringify that same date (using JSON.stringify(date), I get:
"2013-10-24T13:41:47.656Z"
which you can see is not in my current timezone, but is in UTC. So the conversion is happening just before the form gets sent to the server when it gets converted from a javascript object to a JSON string.
The easiest way to do it would be to just change the date to a string of your own choosing prior to sending the date to the server. So instead of letting JSON change the date to UTC, (assuming you don't care about the time of day) you could just do something like this:
var dateStrToSend = $scope.date.getUTCFullYear() + '-' + ($scope.date.getUTCMonth() + 1) + '-' + $scope.date.getUTCDate();
That will give you a UTC-based string that looks like '2013-10-24' and then you can send that to the server, instead of the JSON format which includes the time info. Hopefully that helps.
UPDATE: As #Matt Johnson said, there are two ways to do it. You said: How could we prevent the conversion, or use UTC dates during the whole process?. If you want to use UTC, then use my above explanation. If you want to just "prevent the conversion", you could use the following:
var dateStrToSend = $scope.date.getFullYear() + '-' + ($scope.date.getMonth() + 1) + '-' + $scope.date.getDate();
A bit late but I spent my afternoon on this and someone might find it useful.
Another way to do this declaratively is to use the dateType, dateFormat and modelDateFormat attributes. Set these in either the config or the HTML e.g
angular.module('app').config(function ($datepickerProvider) {
angular.extend($datepickerProvider.defaults, {
dateFormat: 'dd-MMMM-yyyy',
modelDateFormat: "yyyy-MM-ddTHH:mm:ss",
dateType: "string"
});
});
DateFormat is the format the date will be displayed to the user in the date picker while modelDateFormat is the format it will be converted to before being bound to your model.
I also had default values coming from the server which I needed to be bound to the datepicker on page load. I therefore had to update the format the server serialized dates in JSON to match the modelDateFormat. I am using Web API so I used the below.
var jsonSettings = Formatters.JsonFormatter.SerializerSettings;
jsonSettings.DateFormatString = "yyyy-MM-ddTHH:mm:ss";
The "Angular way" is to use the $filter service to format the date returned by the datepicker.
Example (HTML):
{{inpDate | date: 'dd-MM-yyyy'}}
Example (JS):
$scope.processDate = function(dt) {
return $filter('date')(dt, 'dd-MM-yyyy');
}
Plunker here

Java Script: How to ammend a datetime variable to set a specific time?

I need to take a datetime values from an MSSQL based app which is read into the script as 22/12/2010 3:56pm and adjsut the time component toa set time.
I've used what I know of javascript and what I can find in google searches to try and progress this but to no avail.
Premis: I need to read the date time value and set the time portion of the date to 8am, 1pm or 4pm dependent on another field.
The conditional logic portion of the script is fine the date functions aren't so fine.
Current code I'm currently using:
if(fldPriority.Value=='2')
{
var ResDate = new Date(fldTargetResolutionTime.Value);
var newdate = new Date(ResDate.getYear(),ResDate.GetMonth(),ResDate.GetDay(),16,0,0,0);
objReturn = newdate
}
Problem:
The date reads in originally in gmt format 22/12/2010 3:56pm but then gets changes to utc format and the date changes significantly to Wed Oct 12 15:56:00 UTC+12 2011
Any help would be greatly appreciated.
Make a copy of the Date and set the time using UTCHours.
The return value will be the correct Date and time,
but you if need to convert it to a string the string will be local time unless you call newDate.toUTCString();
(or objReturn.toUTCString())
var newdate=new Date(ResDate);
newDate.setUTCHours(16,0,0,0);
objReturn=newDate;

Categories

Resources