Why time format and parse gives different results? - parsing

I'm taking the current time and format it and parse it back. When I compare the result with the current time they are not equal.
Here is a playground example:
https://play.golang.org/p/DDFzi1t8v_-
t := time.Now()
formatted := t.Format("2006-01-02 15:04:05.000 -0700")
parsed, _ := time.Parse("2006-01-02 15:04:05.000 -0700", formatted)
fmt.Println(parsed.Equal(t))
This is working on the playground but not in my local computer because my timezone is +0300.
Here is the output of the same code on my computer:
t : 2018-03-09 13:38:37.229832 +0300 +03 m=+0.000440904
formatted : 2018-03-09 13:38:37.229 +0300
parsed : 2018-03-09 13:38:37.229 +0300 +03
false
How can I make them equal?

The difference is on the precision of the date.
Your time.Now() returns a result with 6 decimals (Microseconds) and you try to format a time with 3 decimals (Milliseconds).
You have to Round your time at Milliseconds like that :
t := time.Now().Round(time.Millisecond)

Related

Moment Display Date according to ISO-8601 Timezone Offset

I am getting a ISO-8601 date string from an API response as follows :
var x1 = 2022-06-22T05:30:00+05:30
or it could be
var x2 = 2022-06-22T08:30:00-05:00
Irrespective of browser timezone I should display the dates as
X1 - 2022-06-22 05:30:30 IST
X2 - 2022-06-22 08:30:00 EST
How can i parse timezone from the offset like -05:00 or +05:30 using moment or luxon?
I tried moment.tz(timestamp) but it defaults to UTC since it needs the second argument.
So i did a bit more digging.
Logically what i want is not possible.
Many timezones shares UTC offset. Hence, there could be ambiguity, if we try to convert an offset to a TimeZone without any other additional info
Hence, I am opting for a solution, where my API response sends a timezone metadata for each date/time field. (I have lat/long info to convert in Tz in my backend)
In front End, i will simply use the timezone info to format my moment object into a desired date-time String.
For example
const timestring = '2022-06-22T00:00:00+00:00';
const timezoneName = "America/Chicago" ;
moment.tz(timestring, timezoneName).format('YYYY-DD-MM hh:mm:ss z');
// Output: 2022-06-21 07:00:00 CDT
Source : https://stackoverflow.com/tags/timezone/info

moment.tz is giving incorrect result

I was trying to convert dates according to selected timezone. I was surprised to see same result for dates with 5 mins of time difference.
For ex,
var x = "2017-07-10T18:30:00.000Z"
var y = "2017-07-10T18:35:00.000Z"
var z = "2017-07-10T18:45:00.000Z"
and tried converting them to using moment.tz:
moment.tz(x, 'America/New_York').format('DD/MM/YYYY HH:MM:SS');
moment.tz(y, 'America/New_York').format('DD/MM/YYYY HH:MM:SS')
moment.tz(z, 'America/New_York').format('DD/MM/YYYY HH:MM:SS')
To my surprise, result was same for all 3 being "10/07/2017 14:07:00".
What's going wrong? Any help will be appreciated.
Short answer:
The issue is that you are using uppercase MM (month) instead of lowercase mm minutes in you format(). Note that, you have the same problem for SS (fractional seconds) and ss (seconds).
General note about you code sample:
Use moment.tz for parsing time string using a given timezone (e.g. 'America/New_York'), moment.tz is not made for converting input to given timezone.
You have to use tz() method to convert a moment object to a given timezone.
Note that your input string ends with Z so it represents time in UTC.
As Matt Johnson pointed out in comments, in your case even moment.tz(input, zone) would convert input to given zone because input string contains the Z (that stays for UTC timezone). Anyway this kind of approach is discouraged.
Here a code sample that parses UTC time string and converts it to 'America/New_York' timezone:
var x = "2017-07-10T18:30:00.000Z";
var y = "2017-07-10T18:35:00.000Z";
var z = "2017-07-10T18:45:00.000Z";
console.log( moment.utc(x).tz('America/New_York').format('DD/MM/YYYY HH:MM:SS') );
console.log( moment.utc(y).tz( 'America/New_York').format('DD/MM/YYYY HH:mm:ss') );
console.log( moment.utc(z).tz( 'America/New_York').format('DD/MM/YYYY HH:mm:ss') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/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>

How to parse Date in IST format in Golang?

time.Date(t.Year(), t.Month(), time.Now().Day(), 10, 0, 0, 0, time.UTC)
I want to set dateTime of 10:00:00 AM in IST format in golang.
It depends on the format of the time you have at hand. Go has some standard time formats ready as consts in the time package, but you can specify your own standard if it's custom. Regarding the time zone, you can parse or output a time in a specific time zone. Here is an example of parsing a time string in IST, and outputting it as UTC. It's not clear from your question what is your precise problem but I hope this helps:
// First, we create an instance of a timezone location object
loc, _ := time.LoadLocation("Asia/Kolkata")
// this is our custom format. Note that the format must point to this exact time
format := "Jan _2 2006 3:04:05 PM"
// this is your timestamp
timestamp := "Jun 25 2015 10:00:00 AM"
// now we parse it, considering it's in IST
t, err := time.ParseInLocation(format, timestamp, loc)
// printing it prints it in IST, but you can set the timezone to UTC if you want
fmt.Println(t, err)
// example - getting the UTC timestamp
fmt.Println(t.UTC())

Delphi tclientdataset .cds datetime binary timeformat unpack

I am trying to parse .cds delphi database file. Simple int values and strings are easy to parse. But the only one i cannot understand is a DateTime format.
I found 6 bytes that affecting DateTime Value
I am using python and the following code:
data = '\x00\x00' + '\xBC\xCE\x6F\xEC\xE7\xCC'
data_long = struct.unpack('Q', data)[0]
But struct.unpack doesnt have 6 byte type values, so i added \x00 \x00 to make 8 byte long value ('Q' option)
Here is small sample .cds file with one row https://yadi.sk/d/PkZKy50YgCmqE
DateTimeIssl value = "16.04.2015 9:25:47"
I found 6 hex values but cant unpack it properly.
Can anyone tell me how to read it, or maybe give me a link to some documentation about .cds file structure?
Update:
OK! Thanks to Deltics for guide me how to read TDateTime. I found some test values on internet and i wrote decode function that converts it to Python datetime object.
data = '\x2E\xD8\x82\x2D\xCE\x47\xE3\x40'
data_double = struct.unpack('d', data)[0]
double_split = str(data_double).split('.')
SECONDS_IN_DAY = 60*60*24
time_from_starting_date = timedelta(days=int(double_split[0]), seconds=int(SECONDS_IN_DAY * (float(double_split[1]) * pow(0.1, len(double_split[1])))))
starting_date = datetime(1899, 12, 30)
result_date = starting_date + time_from_starting_date
print time_from_starting_date
print result_date
For 2E D8 82 2D CE 47 E3 40 it will be 08.02.2008 10:38:00.
Works fine.
But i still cannot found valid 8-bytes for field DateTimeIssl in file that i've linked above. Maybe there a different datetime format?
A Delphi date/time (TDateTime) is a Double precision floating point. This is an 8-byte value. You should not need to add any packing or null bytes. If you are having to do this then you have not identified the double value correctly in the file.
Looking at the sample CDS you linked to, each value that could sensibly be interpreted as a date/time (e.g. DateRoshd, DateTimeIssl) is followed by 8 bytes of data.
After reading the double value, the whole number part of this value indicates the date as the number of days since 30 Dec 1899. The decimal part is the time of day on that date.
e.g.
1.0 = 31 Dec 1899, 00:00 (midnight)
2.5 = 1 Jan 1900, 12:00 (midday)
More information on the Delphi TDateTime data type can be found here.
Responding to myself. Maybe for someone it will be useful.
In binary format, TClientDataSet DateTime contains INTEGER value of milliseconds since 02.01.0001, but stores as a 8-byte DOUBLE
So you have to read 8-bytes, unpack it as a double, then convert value to integer. Here is Python code that worked for me:
data = '\x00\xBC\xCE\x6F\xEC\xE7\xCC\x42' # Time: 2015-04-16 09:25:47
data_double = struct.unpack('d', data)[0]
time_from_starting_date = timedelta(days=-2, milliseconds=long(data_double))
starting_date = datetime(0001, 01, 02)
result_date = starting_date + time_from_starting_date
print "Time:", result_date

Bad conversion from EndOfTheMonth(date) to Variant value

I have a TDateTime value (that I get as result from EndOfTheMonth(date)) to a variant type. The result is wrongly rounded. Let's have a look at example:
data := EndOfTheMonth(date);
V := data;
ShowMessage(DateTimeToStr(data) + ' vs ' + VarToStr(V));
// output is
// data = 2012-01-31 23:59:59
// v = 2012-02-01 // why next day?
Is it designed behaviour?
How to work around this?
ShowMessage(DateTimeToStr(data) + ' vs ' + DateTimeToStr(VarToDateTime(V)));
Update: I would guess the problem is that the last millisecond of the month is very close to 0:00:00 the next day, that is, the TDateTime value (which is basically a double) is very close to an integer (e.g. 41029.9999999884 is very close to 41029) and so the VarToStr function assumes the decimals to be numerical fuzz.

Resources