Delphi: How to get UTC time when DST locally is active - datetime

My first question ever at StackOverflow.
Delphi Embarcadero 10.3 environment.
I want access to UTC time. No matter if DST is active or not on my local computer in my time zone, I do not get the correct UTC DateTime. It reports UTC correctly when Daylight Savings Time is active, but as soon as I test after 11/6/22 02:00 AM the resulting UTC output time is 1 hour too early.
A simple function should according to documentation give me UTC as an output and automatically adjust for local DST offset and Timezone.
Here is the function:
function UTCNow: TDateTime;
var
UTCnowDateTime: TDateTime;
begin
UTCnowDateTime := TTimezone.Local.ToUniversalTime(Now, True);
Result := UTCnowDateTime;
end;
I tested this by setting local time to 11/6/2022 at 1:59:00 AM.
I call the UTCNow function above and get 11/6/2022 and the UTC time 5:59:06 AM.
Then I wait for the time to reach 02:00 AM, where my local computer adjusts for the end of DST and sets the local time to 01:00.
I call the UTCNow function again and get 11/6/2022 and the UTC time 5:00:14 AM.
One hour off ! It should be 06:00:14 AM.
(Note: I ran a VB.net test using DateTime.UtcNow and it works correctly across the DST change, but this doesn't help me...)
Any hints ?

For Windows you can call GetSystemTime which gets the time in UTC. Just need to convert it from a Windows SystemTime to a TDateTime.
function UTCNow: TDateTime;
var
ASystemTime: TSystemTime;
UTCnowDateTime: TDateTime;
begin
GetSystemTime(ASystemTime);
UTCnowDateTime := SystemTimeToDateTime(ASystemTime);
Result := UTCnowDateTime;
end;

Related

Moment return the same value passed to it instead of utc value

Im trying to trasform a date to utc but moment return the same value i use.
for example
moment(date, 'YYYY-MM-DD HH:mm:ss').utc().format('YYYY-MM-DD HH:mm:ss')
if i use date = '2022-01-07 11:30:00' moment return 2022-01-07 11:30:00
do i have to set the timezone of the value first? why moment return the wrong value? it should return +3 hours that date.
You'll need to define the timezone in which the date is, then the offset will be as expected:
Example, using Europe/Amsterdam as timezone
const date = '2022-01-07 11:30:00';
const utc = moment(date, 'YYYY-MM-DD HH:mm:ss')
.tz('Europe/Amsterdam')
.utc()
.format('YYYY-MM-DD HH:mm:ss');
console.log(utc);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.32/moment-timezone-with-data.min.js"></script>
This will output 2022-01-07 10:30:00 since Amsterdam time is -1 compared to UTC.
Small side node, quoting MomentJS Project Status page
We now generally consider Moment to be a legacy project in maintenance mode. It is not dead, but it is indeed done.
In practice, this means:
We will not be adding new features or capabilities.
We will not be changing Moment's API to be immutable.
We will not be addressing tree shaking or bundle size issues.
We will not be making any major changes (no version 3).
We may choose to not fix bugs or behavioral quirks, especially if they are long-standing known issues.
The data you pass in doesn't have any indication of the timezone it's in, so moment is (I believe) assuming it's in utc already.
In related news, look into using the date-fns library instead of moment. Moment is getting old...
Moment github
Moment.js is a legacy project, now in maintenance mode. In most cases,
you should choose a different library.
This returns the same date since you never indicated any timezone
var time = moment("2013-08-26 16:55:00") //this creates time in my tz
You can set a timezone like this:
var time = moment("2013-08-26 16:55:00").tz("America/Los_Angeles");

how can I get a custom timezone datetime from utc timestamp with javascript(node.js)

my backend server stores a utc timestamp with python and send it to frontend.
from datetime import datetime
utcTs = datetime.utcnow().timestamp()
and then frontend app (node.js) get the utcTs , convert it to locale time (or custom timezone)
I code like this:
moment.unix(utcTs).add(8,'hour').format()
because the utcTs is a utc+0 timestamp, how can I initialize a moment object as utc+0, so I can convert it to other timezone easily.
for example, my locale is utc+8.
moment.tz(utcTs,'Asia/Shanghai').format()
return a incorrect time.
is there any gentle way? thanks
The timestamp returned from Python's timestamp() method is in terms of UTC-based seconds from the Unix epoch, so you just need to do the same thing in Moment.
// this is in seconds, but creates a moment in local mode
moment.unix(utcTs).add(8,'hour').format()
// you need to get it in UTC mode with the .utc(). Adding gives a moment 8 hours later.
moment.unix(utcTs).utc().add(8,'hour').format()
// this is how you get it in a fixed offset instead of adding
moment.unix(utcTs).utcOffset('+08:00').format()
Since not all time zones can use fixed offsets, the following is a better approach.
// this is incorrect, as the input would interpreted as milliseconds
moment.tz(utcTs,'Asia/Shanghai').format()
// this is the correct way for it interpreted in terms of seconds
moment.unix(utcTs).tz('Asia/Shanghai').format()

moment.format() returns next day

So Im using Fullcalendar and on dayClick I'm trying to find events that match the day clicked.
var events = $calendar.fullCalendar('clientEvents');
if(events.length > 0) {
for (var i = 0; i < events.length; i++) {
if (date.format('YYYY-MM-DD') == events[i].start.format('YYYY-MM-DD')) {
...
Now
date.format('YYYY-MM-DD')
returns the day I clicked but when the for loop gets to that days events then
events[i].start.format('YYYY-MM-DD')
returns the next day. This seems to be affected by UTC but this applies to ALL days with events. Not just today. I've tried different formats and still the same. Here's something I noticed though:
n
_ambigTime:false
_ambigZone:true
_d:Thu Feb 09 2017 08:00:00 GMT-0500 (EST)
_f:"YYYY-MM-DD HH:mm:ss"
_fullCalendar:true
_i:"2017-02-08 13:00:00"
_isAMomentObject:true
_isUTC:true
_isValid:true
_locale:f
Notice that _d and _i are different. _i is actually the right date/time. So how can I reference that?
All moment properties starting with _ (like _d and _i) are for internal use and should not be used.
If you want to check if two moment object represent the same day you can use isSame passing the second parameter to limit granularity, instead of comparing formatted strings. In your case:
date.isSame(events[i].start, 'day')
The problem is that some of your objects are created in UTC mode (_isUTC: true), so they will be displayed using UTC time (previous day in some cases) instead of local time.
More info about UTC mode here:
By default, moment parses and displays in local time.
If you want to parse or display a moment in UTC, you can use moment.utc() instead of moment().
This brings us to an interesting feature of Moment.js. UTC mode.
While in UTC mode, all display methods will display in UTC time instead of local time.

events (as a json feed), start end parameters unix timestamp, are different if I change my OS time zone

I'm using the fullcalendar plugin and would appreciate if someone can give me a hand.
I am getting json events through a PHP URL.
something like this:
$('#calendar').fullCalendar({ events: "/myfeed.php" });
So in my php page that returns the events, I am getting 3 GET parameters:
'_'
'start'
'end'
The start and end parameter, indicate the date in UNIX timestamp.
So far so good, the problem that occurs is that if I change the time zone on my OS. also change these parameters start and end, for the same query in the same day in the calendar.
the weirdest part is that it only happens in Mozilla Firefox.
in Google Chrome, this problem does not occur.
e.g.
I have set my time zone ((UTC-04: 00) Santiago)
I'm referring to the day 09.09.2012 on the agenda,
firebug shows me that these parameters are being sent to my php page
_ 1347245953581
end 1347246000
start 1347159600
but if I change the time zone from my OS to ((UTC-03: 00) Buenos Aires)
consulting on 09.09.2012 on the agenda,
are other parameters which are now sent to the PHP page.
_ 1347246338047
end 1347332400
start 1347246000
Being that it is the same day, are other start and end parameters which are sent to check for events.
There is an ignoreTimezone option on the fullcalendar that might help. I'm not sure if it affects the start/end time passed to the feeds.
http://arshaw.com/fullcalendar/docs/event_data/ignoreTimezone/
Another option is to convert the passed timestamp to a Date object and get the local data from the Date object afterwards and use that in your queries.
Convert a Unix timestamp to time in JavaScript
I know it is not the exact answer, but it might help you out a bit.
Here is a sample piece of PHP code to convert the passed timestamp into a local formatted date:
$startts = $_REQUEST["start"]; // original timestamp
$startdt = new DateTime('now', new DateTimeZone('Europe/Oslo') ); // setup a local datetime
$startdt->setTimestamp($startts); // Set the date based on timestamp
echo $startdt->format('Y-m-d H:i:s'); // Output local date and time

Flex- Time Zone Conversion

How to convert date and time to CDT time Zone in flex4
Regards,
Sushma
The Date object in Flash is always set to the computer's time settings. If the computer is already in the CDT timezone, then just getting any property from the object will be good. However, if you want to do a timezone 'conversion' into a timezone that the computer is not set to, you can get the UTC time and offset it like this:
var date:Date = new Date();
var timezone:int = -5;
date.hours = date.hoursUTC + timezone;
However, you're trying to get the actual CDT time, which only works during the summer in certain areas. For this, it's impossible for Flash to know exactly when that is UNLESS you code the exceptions (ie. if between this date and that date, do -6, else do -5) and you also need to know the actual location of the user (which is impossible through Flash unless the user gives you that info).
Can I ask why you need to know such a thing?

Resources