I've found a couple of existing StackoverFlow questions on this but nothing very definite.
I have a local datetime. I want this in UTC. my local datetime does not have a 'Z' at the end or any offset information.
I first tried:
moment(mylocaldatetime).toISOString() #works fine because this method always returns time in UTC
But for consistency with other code I didn't want to use to ISOString() so I did this:
moment(mylocaldatetime).utc().format()
This seems to work fine. If the browser running this code is in UTC + 1 I get a datetime one hour less than mylocaldatetime (with an offset string if I specify that in the format). I.e. it has treated mylocaldatetime as a local time, taken account of my current time zone, and given me my local time as UTC.
However. This appears to contradict the moment.js docs which are pretty clear that:
If you want to parse or display a moment in UTC, you can use moment.utc() instead of moment(). - Notice the 'parse'.
and
Moment normally interprets input times as local times (or UTC times if moment.utc() is used).
If these doc comments were true this line:
moment(mylocaldatetime).utc().format()
should treat mylocaldatetime as if it were utc and then output this datetime in utc - no difference. No conversion. But that is not what I get.
Maybe what this line moment(mylocaldatetime).utc().format() is saying is:
create a moment object in local mode with mylocaldatetime. Then put the moment object into utc mode. So now when we format for display we output as utc. IF this is the case I think the docs could be made clearer.
Related
This question already has answers here:
How to make a timezone aware datetime object
(15 answers)
Closed 6 years ago.
I've got a datetime which has no timezone information. I'm now getting the timezone info and would like to add the timezone into the existed datetime instance, how can I do?
d = datetime.datetime.now()
tz = pytz.timezone('Asia/Taipei')
How to add the timezone info tz into datetime a
Use tz.localize(d) to localize the instance. From the documentation:
The first is to use the localize() method provided by the pytz library. This is used to localize a naive datetime (datetime with no timezone information):
>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0))
>>> print(loc_dt.strftime(fmt))
2002-10-27 06:00:00 EST-0500
If you don't use tz.localize(), but use datetime.replace(), chances are that a historical offset is used instead; tz.localize() will pick the right offset in effect for the given date. The US Eastern timezone DST start and end dates have changed over time, for example.
When you try to localize a datetime value that is ambiguous because it straddles the transition period from summer to winter time or vice-versa, the timezone will be consulted to see if the resulting datetime object should have .dst() return True or False. You can override the default for the timezone with the is_dst keyword argument for .localize():
dt = tz.localize(naive, is_dst=True)
or even switch off the choice altogether by setting is_dst=None. In that case, or in the rare cases there is no default set for a timezone, an ambiguous datetime value would lead to a AmbiguousTimeError exception being raised. The is_dst flag is only consulted for datetime values that are ambiguous and is ignored otherwise.
To go back the other way, turn a timezone-aware object back to a naive object, use .replace(tzinfo=None):
naivedt = awaredt.replace(tzinfo=None)
If you know that your original datetime was "measured" in the time zone you are trying to add to it, you could (but probably shouldn't) use replace rather than localize.
# d = datetime.datetime.now()
# tz = pytz.timezone('Asia/Taipei')
d = d.replace(tzinfo=tz)
I can imagine 2 times when this might make sense (the second one happened to me):
Your server locale is set to the incorrect time zone and you are trying to correct a datetime instance by making it aware of this incorrect timezone (and presumably later localizing it to the "correct" time zone so the values of now() match up to other times you are comparing it to (your watch, perhaps)
You want to "tag" a time instance (NOT a datetime) with a time zone (tzinfo) attribute so that attribute can be used later to form a full datetime instance.
Why does this show the same time twice:
=Now() & ' ' & TimeZone() & '\n' & ConvertToLocalTime(Now(), 'UTC') & ' UTC'
This shows:
2017-04-08 07:53:27 GMT-08:00
2017-04-08 07:53:27 UTC
I'm trying to conditionally-format a pivot table expression based on whether its start timestamp is "in the future". The field in question is correct (ConvertToLocalTime([Start Time], 'UTC') shows the correct timestamp), and the local time is also correct, but I cannot accurately compare my local non-UTC time with another from a different time zone.
From the helpfile you will notice this is to convert a UTC or GMT timestamp to local time as a dual value
So usage would be as follows:
=ConvertToLocalTime(UTC(), 'GMT-05:00')
For your example:
=ConvertToLocalTime(UTC(), TimeZone() ) & ' ' & TimeZone() & '\n' & UTC() & ' UTC'
Helpfile source: http://help.qlik.com/en-US/qlikview/12.1/Subsystems/Client/Content/Scripting/DateAndTimeFunctions/converttolocaltime.htm
Part of the problem is that I had mis-read the portion of the ConvertToLocalTime docs, namely that it requires a GMT or UTC timestamp to operate. (I'm accustomed to other programming languages where the timezone is stored in or with the timestamp and can adjust automatically.)
Another aspect to this (not stated in the original question) is that QV is relying on the underlying OS for some timezone information, and I believe that Windows (ergo both QV desktop and QV server) is doing something odd, I think incorrect: despite the fact that UTC does not observe daylight savings time, Windows provides different times for "UTC" and "UTC+00:00". (If there is a valid explanation for this behavior, please comment!)
ConvertToLocalTime(UTC()) : 2017-04-20 10:12:17
ConvertToLocalTime(UTC(), "UTC") : 2017-04-20 17:12:17
ConvertToLocalTime(UTC(), "UTC+00:00") : 2017-04-20 18:12:17 (huh?)
ConvertToLocalTime(UTC(), "UTC+00:00", "True") : 2017-04-20 17:12:17
(Double quotes are shown above for the text, single-quotes for the actual function call.) ConvertToLocalTime() has a third argument, ignore_dst which may be used to mitigate this, but because it's a nuclear option that cannot be safely applied to non-UTC timezones, I cannot programmatically deal with time zones without several other checks.
Bottom line: QV does not store the time zone with a timestamp. That is, it relies on the programmer to track the source of the timestamp and do conversion as needed. This suggests that if time zones are ever used or in question, all data should be stored in "UTC" proper (not "UTC+00:00") so that ConvertToLocalTime() can be used to easily convert into other zones. (Many suggested TZ best practices apply here.)
Related: not all database timestamp types are supported by QV. For example, SQL Server's datetimeoffset is not supported, so manual parsing is required in order to preserve time zone and correctly use the numeric/timestamp dual.
I am wondering what this does:
newM = moment("2015-08-11T13:00:00.000000Z", "YYYY-MM-DDTHH:mm:ss.SSSS[Z]", true)
Specifically - the [Z] in the format string.
I am using a library (react-bootstrap-datetimepicker) which uses moment. This library (React component) takes a parameter 'format' which is used as the second parameter to moment
I can't see what the [Z] is doing. But I have to do this rather than just 'Z' to get the result I want when I format the moment object for display with this string: newM.format('YYYY-MM-DD HH:mm:ss.SSSZ').
EDIT:
to be clear: I understand that 'Z' will cause the datetime passed to be treated as UTC, as per the docs. But what is the significance of the square brackets - which are not in the docs.
For everyone who cares about consistency due to the missing Z at the end - try to add [Z] to your format.
Example: .format('YYYY-MM-DDTHH:mm:ss[Z]') so the result is: 2019-11-26T10:39:54Z
More detailed explanation you can find in this github issue.
Z does not cause the time to be treated as UTC when used in the format. It matches a timezone specifier:
Format: Z ZZ
Example: +12:00
Description: Offset from UTC as +-HH:mm, +-HHmm, or Z
And under the documentation for format:
To escape characters in format strings, you can wrap the characters in
square brackets.
By specifying Z in brackets, you are matching a literal Z, and thus the timezone is left at moment's default, which is the local timezone.
Unless you specify a time zone offset, parsing a string will create a
date in the current time zone.
If your time is really in UTC, this is probably not desired behavior. If you want to parse it as UTC but display it in local time, use Z and then call local() on the resulting moment object, so most likely what you want is:
// Parse with timezone specifier (which is UTC here) but convert to local time
newM = moment("2015-08-11T13:00:00.000000Z", "YYYY-MM-DDTHH:mm:ss.SSSSZ", true).local();
Does the below 2 syntaxes are same,
moment(1456261200367, 'H:mm:ss.SSS').utc().valueOf() //1456343786120
moment(1456261200367 +0000, 'H:mm:ss.SSS Z').valueOf() //1456325786120
but as you could see if both of them coverts the given value to UTC mode then why there is a difference in the output?
Also I would like to know how a.valueOf() and b.valueOf() are same, when a.format() and b.format() are different, because moment() (moment parses and displays in local time) is different from moment.utc() (displays a moment in UTC mode)
var a = moment();
var b = moment.utc();
a.format();
b.format();
a.valueOf();
b.valueOf();
In the first part, you're using it incorrectly. You've passed numeric input which would normally be interpreted as a unix timestamp, but then you've supplied a string-based format string so the number is converted to a string. The format string here is telling moment how the input is specified, but it doesn't match what you're actually parsing.
This doesn't error though, because by default moment's parser is in "forgiving" mode. You can read more about this in the docs.
The correct way to pass a timestamp into moment is with one of these:
moment(1456261200367)
moment(1456261200367).utc()
moment.utc(1456261200367)
The last two are equivalent, but the moment.utc(timestamp) form is prefered.
With any of those, all three will have the same .valueOf(), which is just the timestamp you started with. The difference is in the mode that the moment object is in. The first one is in local mode, reflecting the time zone of the computer where it's running, while the other two are in UTC mode.
This is evident when you format the output using the format function, as with other many other functions. I believe that answers your second question as well.
I parse this date "22/11/11" into a DateTime object called s. When I do s.getDayOfMonth() it gives me 22 which is right. However, when I convert the DateTime object to a Date object and try to get the date using s.toDate().getDate() it returns 24 which is not right. Does anyone have an idea why is this happening ?
The Joda-Time DateTime.toDate() method converts to a java.util.Date with the same millisecond instant. The java.util.Date.getDate() method uses the local default time-zone to return its value, whereas DateTime.getDayOfMonth() uses the time-zone stored in the DateTime object. If the two time-zones are different, you may see a difference, explaining the 22/24 you observe.
To understand further, print the time-zone of the DateTime, and the default Java zone TimeZone.getDefault() used by java.util.Date.