Display ICU UDate formatted for different timezones - icu

In the following example, I would like to format EPOCH (1/1/1970) in different time zones. For example, I may wish to format EPOCH using the Los Angeles time zone and/or format EPOCH using the New York timezone.
UErrorCode uErrorCode = U_ZERO_ERROR;
UnicodeString unicodeString;
UDate uDate;
icu::Locale locale = icu::Locale("en");
TimeZone* timeZone = TimeZone::createTimeZone("America/Los_Angeles");
Calendar* calendar = Calendar::createInstance(timeZone, uErrorCode);
// setting calendar to EPOCH, e.g. zero MS from 1/1/1970
calendar->setTime(0, uErrorCode);
// get calendar time as milliseconds (UDate)
uDate = calendar->getTime(uErrorCode);
DateFormat* dateFormat = DateFormat::createDateTimeInstance(
icu::DateFormat::MEDIUM, // date style
icu::DateFormat::SHORT, // time style
locale);
unicodeString = dateFormat->format(uDate, unicodeString, uErrorCode);
std::string str;
unicodeString.toUTF8String(str);
std::cout << "Date: " << str;
// Use getOffset to get the stdOffset and dstOffset for the given time
int32_t stdOffset, dstOffset;
timeZone->getOffset(uDate, true, stdOffset, dstOffset, uErrorCode);
std::cout << " | ";
std::cout << "Time zone STD offset: " << stdOffset / (1000 * 60 * 60) << " | ";
std::cout << "Time zone DST offset: " << dstOffset / (1000 * 60 * 60) << std::endl;
The problem that I have is that the output is not formatted respective to the time zone.
Here is the output when using the Los Angeles time zone:
Date: Dec 31, 1969, 6:00 PM | Time zone STD offset: -8 | Time zone DST offset: 0
Here is the output when using the New York time zone:
Date: Dec 31, 1969, 6:00 PM | Time zone STD offset: -5 | Time zone DST offset: 0
Please notice that the date is not EPOCH and secondly notice that the dates and times for both outputs are identical. The offsets are correct, but the date/time display is not.
UPDATE
It is important to note that the displayed date/time is 6 hours behind since I'm currently (-6 UTC) meaning that you ADD 6 hours to Dec. 31, 1969 at 6:00PM which would then equal EPOCH Jan. 1, 1970 12:00AM.
ICU is using my PC's timezone automatically since I have found no way to specify timezone when formatting date/time using DateFormat::Format(...). If format() accepted a timezone argument to override my PC's local timezone, I would not be having this issue.

You should call dateFormat->setTimeZone(*timeZone) to specify time zone.

#earts had it right, because you are formatting based on the scalar time value and not the calendar.
Alternatively, you can format the Calendar object itself, which will use the timezone and time from that calendar:
unicodeString = dateFormat -> format(*calendar,
unicodeString,
(FieldPositionIterator*) nullptr, // ignored
uErrorCode);
Note, though, that using the above function, the calendar type had better match that of the dateformat. An easy way to do that is to make sure you pass in the locale parameter when creating the calendar:
// above:
Calendar* calendar = Calendar::createInstance(timeZone, locale, uErrorCode);

Related

Is there any NodeJs class/function which is similar to Environment.TickCount on c#?

This code is running on c#
int x = Environment.TickCount;
docs for Environment.TickCount
Gets the number of milliseconds elapsed since the system started. TickCount cycles between Int32.MinValue, which is a negative number, and Int32.MaxValue once every 49.8 days.
TickCount will increment from Zero to (2147483647) for approximately 24.9 days, then jump back to (-2147483648), which is a negative number, then increment back to zero during the next 24.9 days.
We can use int result = Environment.TickCount & Int32.MaxValue; to make it rotate between (0) and (2147483647) for every 24.9 days
I want an equivalent method in NodeJS, which would yield the same result.
I made a search on NodeJS npmjs but didn't find similar function
os.uptime() is the closest method to what you need which
Returns the system uptime in number of seconds
NodeJS docs
But this is a valid question that what will be the max limit for the above method.?
In NodeJS the max safe integer is Number.MAX_SAFE_INTEGER that is 9007199254740991. Which is basically 289583309.373 years. So I guess we will have to assume this as the max value for said method.
If you want the functionality as of c#'s TickCount, you will need to create your own custom method, maybe something like given below:
// this method will cycle between 0 and 2147483647
function TickCount() {
const miliseconds_elapsed = os.uptime() * 1000; // convert the time in miliseconds
return miliseconds_elapsed % 2147483647;
}
// this method will cycle between -2147483648 to 2147483647
// note: it will not start from 0
function TickCount() {
const miliseconds_elapsed = os.uptime() * 1000; // convert the time in miliseconds
return (miliseconds_elapsed % 4294967296) - 2147483648;
}
// this method will cycle between -2147483648 to 2147483647
// note: it will start from 0 goes to 2147483647
// then comes back to -2147483648 and starts the cycle
function TickCount() {
const miliseconds_elapsed = os.uptime() * 1000; // convert the time in miliseconds
if (miliseconds_elapsed <= 2147483647) {
return miliseconds_elapsed;
}
return ((miliseconds_elapsed - 2147483648) % 4294967296) - 2147483648;
}
The Microsoft docs say Environment.TickCount is an integer that "contains the amount of time in milliseconds that has passed since the last time the computer was started".
When searching for that I found this question and the answers suggest to use process.uptime() oros.uptime()

How to get a duration of 1 day with Rust chrono?

I am dealing with some Rust code that works with durations of days but the implementation of Duration::days(n) is, per the documentation n * 24 * 60 * 60 seconds, which isn't n days because not all days are 24 * 60 * 60 seconds.
This behaviour is well documented:
pub fn days(days: i64) -> Duration
Makes a new Duration with given number of days. Equivalent to
Duration::seconds(days * 24 * 60 * 60) with overflow checks. Panics
when the duration is out of bounds.
Is there a way with Rust Chrono to get a duration that is, strictly, 1 day rather than a number of seconds and is compatible with the DateTime types? Not all days are the same number of seconds. seconds and days are quite different units. If there were such a function then the following would always give a result that is the same time of day on the following day?
let start = Local.now();
let one_day_later = start + function_that_returns_a_duration_of_days(1);
Again, Duration:days(1) is not such a function because it returns 1 * 24 * 60 * 60 seconds, rather than 1 day.
For example, with TZ set to America/Denver the following:
let start = Local.ymd(2019, 3, 10).and_hms(0, 0, 0);
println!("start: {}", start);
let end = Local.ymd(2019, 3, 11).and_hms(0, 0, 0);
println!("end: {}", end);
let elapsed_seconds = end.timestamp() - start.timestamp();
println!("elapsed_seconds: {}", elapsed_seconds);
let end2 = start + Duration::days(1);
println!("end2: {}", end2);
let elapsed_seconds2 = end2.timestamp() - start.timestamp();
println!("elapsed_seconds2: {}", elapsed_seconds2);
Returns:
start: 2019-03-10 00:00:00 -07:00
end: 2019-03-11 00:00:00 -06:00
elapsed_seconds: 82800
end2: 2019-03-11 01:00:00 -06:00
elapsed_seconds2: 86400
It adds 86400 seconds, rather than 1 day.
I can get the correct result with:
let one_day_later =
(start.date() + Duration::days(1)).and_hms(start.hour(), start.minute(), start.second());
But I would prefer a function that returns a duration of days and in general would like to know more about Rust Chrono capabilities for handling durations. Does it have durations with units other than seconds? What about weeks, months and years, which also have variable numbers of seconds.
I should probably say that I don't know Rust, only having worked with it for a few days now and I haven't much read the source code. I did look at it, but find it difficult to understand due to my limited familiarity with the language.
A Duration is an amount of time. There is no amount of time that when added to an instant, always yields the same time on the next day, because as you have noticed, calendar days may have different amounts of time in them.
Not only years, weeks and days, but even hours and minutes do not always comprise the same amount of time (Leap second). A Duration is an amount of time, not a "calendar unit". So no, a Duration is not capable of expressing an idea like "same time next week".
The easiest way to express "same time next day" is with the succ and and_time methods on Date:
let one_day_later = start.date().succ().and_time(start.time());
and_time will panic if the time does not exist on the new date.

Sometimes different results of mktime in windows and in linux

Here is the function
time_t time_from_string(const char* timestr)
{
if (!timestr)
return 0;
struct tm t1;
memset(&t1, 0, sizeof(t1));
int nfields = sscanf(timestr, "%04d:%02d:%02d %02d:%02d:%02d",
&t1.tm_year, &t1.tm_mon, &t1.tm_mday, &t1.tm_hour,
&t1.tm_min, &t1.tm_sec);
if (nfields != 6)
return 0;
t1.tm_year -= 1900;
t1.tm_mon--;
t1.tm_isdst = -1; // mktime should try itself to figure out what DST was
time_t result = mktime(&t1);
return result;
}
When I call it with the argument "2007:11:14 11:19:07", it returns 1195028347 in Linux (Ubuntu 12.04, gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3) and 1195024747 in Windows (windows 7, Visual Studio 2010).
As can be seen, time difference is 3600.
I run both operating systems on the same computer (dual-boot), which is in the MSK time zone.
Both OSes are synchronized with the internet time, and their system clock show correct time.
When I call this function with another argument, "2012:08:21 18:20:40", I get 1345558840 in both systems.
Why does the results differ in several cases?
EDIT
Forgot to mention. I control the contents of the t1 variable after call to mktime().
In both systems:
t1.tm_sec = 7;
t1.tm_min = 19;
t1.tm_hour = 11;
t1.tm_mday = 14;
t1.tm_mon = 10;
t1.tm_year = 107;
t1.tm_wday = 3;
t1.tm_yday = 317;
t1.tm_isdst = 0;
Please, mention the last line. Both systems determine that there is no daylight savings in effect.
Linux additionally shows the following fields in struct tm:
t1.gmtoff = 10800;
t1.tm_zone = "MSK";
From Wikipedia: Moscow Time
Until 2011, during the winter, between the last Sunday of October and the last Sunday of March, Moscow Standard Time (MSK, МСК) was 3 hours ahead of UTC, or UTC+3; during the summer, Moscow Time shifted forward an additional hour ahead of Moscow Standard Time to become Moscow Summer Time (MSD), making it UTC+4.
In 2011, the Russian government proclaimed that daylight saving time would in future be observed all year round, thus effectively displacing standard time—an action which the government claimed emerged from health concerns attributed to the annual shift back-and-forth between standard time and daylight saving time. On 27 March 2011, Muscovites set their clocks forward for a final time, effectively observing MSD, or UTC+4, permanently.
Since Moscow observed winter time (UTC+3) on 2007-11-14, 11:19:07 MSK was 08:19:07 UTC, and the Unix timestamp was 1195028347.
It looks like the value you get on Linux is correct, and the value you get on Windows seems to assume UTC+4 which is incorrect.

Visual C++ how to convert Datetime to number of seconds since 1970

I am trying to convert Datetime:
http://msdn.microsoft.com/en-us/library/03ybds8y
to the number of seconds since 1970 using Visual C++.
I searched many solutions but could not make any of them work.
Thanks
You can do this using a TimeSpan of the difference between the two dates. Something like this:
DateTime dtDateYouWantToConvert = /* .... */
DateTime dtReference(1970, 1, 1, 0, 0, 0);
TimeSpan tsDiff = dtDateYouWantToConvert - dtReference;
// calculate number of seconds (including fractional) since 1/1/1970
double dSeconds = tsDiff.TotalSeconds;

Time Zone code translation from Windows to Linux in FreePascal

I have this code that works in FreePascal under Windows and need to translate it to Linux but I'm completely lost on the Time Zone Bias value:
function DateTimeToInternetTime(const aDateTime: TDateTime): String;
{$IFDEF WIN32}
var
LocalTimeZone: TTimeZoneInformation;
{$ENDIF ~WIN32}
begin
{$IFDEF WIN32}
// eg. Sun, 06 Nov 1994 08:49:37 GMT RFC 822, updated by 1123
Result := FormatDateTime('ddd, dd mmm yyyy hh:nn:ss', aDateTime);
// Get the Local Time Zone Bias and report as GMT +/-Bias
GetTimeZoneInformation(LocalTimeZone);
Result := Result + 'GMT ' + IntToStr(LocalTimeZone.Bias div 60);
{$ELSE}
// !!!! Here I need the above code translated !!!!
Result := 'Sat, 06 Jun 2009 18:00:00 GMT 0000';
{$ENDIF ~WIN32}
end;
This guy has the answer: http://www.mail-archive.com/fpc-pascal#lists.freepascal.org/msg08467.html
So you'll want to add the uses clause:
uses unix,sysutils,baseunix
variables to hold the time / timezone:
var
timeval: TTimeVal;
timezone: PTimeZone;
..and get the 'minutes west'.
{$ELSE}
Result := FormatDateTime('ddd, dd mmm yyyy hh:nn:ss', aDateTime);
TimeZone := nil;
fpGetTimeOfDay (#TimeVal, TimeZone);
Result := Result + 'GMT ' + IntToStr(timezone^.tz_minuteswest div 60);
{$ENDIF ~WIN32}
I haven't done a lot of pascal lately, so these is just a hint, rather than a complete answer.
But check out your compiler how to call and link c-code. Then you can use time.h similar as in this C-example:
/* localtime example */
#include <stdio.h>
#include <time.h>
int main ()
{
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
printf ( "Current local time and date: %s", asctime (timeinfo) );
return 0;
}
This program will output something like
Current local time and date: Sat Jun 06 18:00:00 2009
You can use sprintf instead of printf to "print" into an array of characters, and strftime to give a format string how similar to 'ddd, dd mmm yyyy hh:nn:ss' (probably "%a, %d %b %Y %H:%M:%S") and use the 'long int timezone' global variable instead of 'LocalTimeZone.Bias'.
I guess the main hurdle is to figure out how to call the c-code. Maybe you can even use time.h directly from pascal, I would investigate that.

Resources