How to Parse Milliseconds

SimpleDateFormat is not parsing the milliseconds correctly

I'm not entirely sure, but the JavaDoc states this:

For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.

This indicates that the milliseconds from 2011-08-23 14:57:26.9 would be parsed as 9 instead of 900. Adding the trailing zeros might work: 2011-08-23 14:57:26.900.

How can I parse a time string containing milliseconds in it with python?

Python 2.6 added a new strftime/strptime macro %f. The docs are a bit misleading as they only mention microseconds, but %f actually parses any decimal fraction of seconds with up to 6 digits, meaning it also works for milliseconds or even centiseconds or deciseconds.

time.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S.%f')

However, time.struct_time doesn't actually store milliseconds/microseconds. You're better off using datetime, like this:

>>> from datetime import datetime
>>> a = datetime.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S.%f')
>>> a.microsecond
123000

As you can see, .123 is correctly interpreted as 123 000 microseconds.

Convert String to Date with Milliseconds

The Date class stores the time as milliseconds, and if you look into your date object you will see that it actually has a time of 1598515567413 milliseconds.

You are fooled by the System.out.println() which uses Date's toString() method. This method is using the "EEE MMM dd HH:mm:ss zzz yyyy" format to display the date and simply omits all milliseconds.

If you use your formatter, which has milliseconds in its format string, you will see that the milliseconds are correct:

System.out.println(formatter.format(dateFormatter));

outputs 2020-08-27T10:06:07.413

How to parse date-time with two or three milliseconds digits in java?

tl;dr

No need to define a formatter at all.

LocalDateTime.parse(
"2017-11-21 18:11:14.05".replace( " " , "T" )
)

ISO 8601

The Answer by Sleiman Jneidi is especially clever and high-tech, but there is a simpler way.

Adjust your input string to comply with ISO 8601 format, the format used by default in the java.time classes. So no need to specify a formatting pattern at all. The default formatter can handle any number of decimal digits between zero (whole seconds) and nine (nanoseconds) for the fractional second.

Your input is nearly compliant. Just replace the SPACE in the middle with aT.

String input = "2017-11-21 18:11:14.05".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );

ldt.toString(): 2017-11-21T18:11:14.050


Sample Image

how to time.Parse() comma separate milliseconds in go

It's a bug already filed here

The behaviour is documented as such: "A fractional second is represented by adding a period and zeros to the end of the seconds section of layout string, as in "15:04:05.000" to format a time stamp with millisecond precision.

Workaround for that would be replacing "," with "."

package main

import (
"time"
"fmt"
"strings"
)

func main() {
ts := "2020-05-08 22:02:00,845"
ts = strings.Replace(ts, ",", ".", -1)

d, err := time.Parse("2006-01-02 15:04:05.000", ts)
if err != nil{
print(err.Error())
}
fmt.Println(d)
}

here is the Playground

using simpledateformat to parse string date with 6 digit of milliseconds

Instead of the long deprecated SimpleDateFormat and java.util.Date, you should use the new DateTimeFormatter and LocalDateTime in the java.time and java.time.format packages. If for no other reason than SimpleDateFormat does not offer nanosecond resolution (and your input appears to have nanoseconds).

Something like,

String date = "2019-07-04 00:32:08:627158";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"yyyy-MM-dd HH:m:ss:nnnnnn");
LocalDateTime ldt = LocalDateTime.parse(date, formatter);
DateTimeFormatter outFormatter = DateTimeFormatter.ofPattern(
"dd-MMM-yy hh.mm.ss.nnnnnn a");
System.out.println(outFormatter.format(ldt));

Outputs

04-Jul-19 12.32.08.627158 AM

If you want JUL add a toUpperCase() call, and if you need a literal extra three zeros add them in the outFormatter. Like,

DateTimeFormatter outFormatter = DateTimeFormatter.ofPattern(
"dd-MMM-yy hh.mm.ss.nnnnnn000 a");
System.out.println(outFormatter.format(ldt).toUpperCase());

Outputs

04-JUL-19 12.32.08.627158000 AM

It isn't clear where those three zeros came from, if you wanted more precision I would have used

DateTimeFormatter outFormatter = DateTimeFormatter.ofPattern(
"dd-MMM-yy hh.mm.ss.nnnnnnnnn a");
System.out.println(outFormatter.format(ldt).toUpperCase());

But that outputs (as I would expect)

04-JUL-19 12.32.08.000627158 AM

How to parse milliseconds?

Courtesy of the ?strptime help file (with the example changed to your value):

> z <- strptime("2010-01-15 13:55:23.975", "%Y-%m-%d %H:%M:%OS")
> z # prints without fractional seconds
[1] "2010-01-15 13:55:23 UTC"

> op <- options(digits.secs=3)
> z
[1] "2010-01-15 13:55:23.975 UTC"

> options(op) #reset options

Parse CIM_DateTime with milliseconds to Java Date

Modify the input

As far as I know, none of the three common date-time frameworks for Java (the old bundled java.util.Date/.Calendar/java.text.SimpleDateFormat classes, the Joda-Time framework, or the java.time framework built into Java 8 and later) allow for an offset-from-UTC as a total number of minutes.

As suggested by Sotirios Delimanolis, you must modify the offset-from-UTC to convert from a number of total minutes to the standard number of hours and minutes (and seconds – a possibility ignored by that odd Microsoft format). So -420 should become -07:00 or -07:00:00.

java.time

You are using the troublesome old date-time classes bundled with the earliest versions of Java. The old classes are now legacy, and have been supplanted by the java.time framework built into Java 8 and later, and largely back-ported to Java 6 & 7 by the ThreeTen-Backport project and further adapted to Android.

The java.time classes have a resolution of nanoseconds, for up to nine digits of a decimal fraction of second. So no problem handling your inputs 4-6 digits of fractional second.

Our strategy has two parts: (a) Modify the input to convert that offset-from-UTC, and (b) Parse the modified input string as a date-time object.

Modify input

First we change the input from 20160513072950.782000-420 to 20160513072950.782000-07:00:00. We do this by extracting the characters trailing after the + or -, the 420 in this case.

// Modify the input to replace offset as a number of minutes to the standard format, a number of hours, minutes, and seconds.
String input = "20160513072950.782000-420";
String offsetInMinutesAsString = input.substring ( 22 );

Convert that to a long, and create a LocalTime object so that we can generate a string in the format of HH:mm:ss.

long offsetInMinutes = Long.parseLong ( offsetInMinutesAsString );
LocalTime offsetAsLocalTime = LocalTime.MIN.plusMinutes ( offsetInMinutes );
String offsetAsString = offsetAsLocalTime.format ( DateTimeFormatter.ISO_LOCAL_TIME );

Replace those trailing characters with our generated string.

String inputModified = ( input.substring ( 0 , 22 ) + offsetAsString );

Parse string to date-time object

Define a custom formatting pattern by which to parse that string into a OffsetDateTime object.

// Parse the modified input as an OffsetDateTime.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "yyyyMMddHHmmss.SSSSSSZZZZZ" , Locale.US );
OffsetDateTime odt = OffsetDateTime.parse ( inputModified , formatter );

Dump to console.

System.out.println ( "input: " + input + " | inputModified: " + inputModified + " | odt: " + odt );

input: 20160513072950.782000-420 | inputModified: 20160513072950.782000-07:00:00 | odt: 2016-05-13T07:29:50.782-07:00

Convert

I strongly suggest avoiding the old date-time classes. But if you must use a java.util.Date object to interoperate with old date-time code, you can convert.

Look for new methods added to the old classes for conversion. For this conversion we use java.util.Date.from. We need to feed that conversion method a Instant object, a moment on the timeline in UTC with a resolution of nanoseconds. We can extract one from our OffsetDateTime.

Instant instant = odt.toInstant();
java.util.Date utilDate = java.util.Date.from( instant );

For more info about converting, including a nifty diagram, see my Answer to another Question. Keep in mind that we are working with only a mere offset-from-UTC in our input strings and our OffsetDateTime, not a full time zone. A time zone is an offset plus rules for handling anomalies such as Daylight Saving Time (DST). Both the Instant and the java.util.Date are in UTC (an offset of zero).

How to convert millisecond (uint64) into Time Format RFC3999 with millisecond (string) in GO

You are asking for an RFC3339 formatted string, with seconds reported to the nearest millisecond. There's no format string in the time package for this (only with whole seconds and nanosecond accuracy), but you can make your own.

Here's the string for seconds to the nearest nanosecond, copied from the standard library:

RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"

You can make a millisecond version of this easily enough by removing the .999999999 (report time to the nearest nanosecond, removing trailing zeros) to .000 (report time to the nearest millisecond, don't remove trailing zeros). This format is documented under time.Layout in the package docs https://pkg.go.dev/time#pkg-constants:

RFC3339Milli = "2006-01-02T15:04:05.000Z07:00"

Code (playground link):

package main

import (
"fmt"
"time"
)

const RFC3339Milli = "2006-01-02T15:04:05.000Z07:00"

func main() {
ms := int64(1645286399999) //My Local Time : Sat Feb 19 2022 23:59:59
var loc = time.FixedZone("UTC-4", -4*3600)
fmt.Println(time.UnixMilli(ms).In(loc).Format(RFC3339Milli))
}

Output:

2022-02-19T11:59:59.999-04:00


Related Topics



Leave a reply



Submit