I am trying to use DateTimeParser and DateTimeFormatter to format the date time. My requirement is to format the input string to "yyyy-MM-dd'T'HH:mm:ssZ" format irrespective of whether the input has milliseconds or not. I am using below code to parse the input. But so far I can get it working for only with or without milliseconds.
This is my method:
public static DateTime convertDateTime(String dateTime){
DateTimeParser parsers = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").getParser();
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(parsers ).toFormatter().withLocale(Locale.US).withChronology(ISOChronology.getInstanceUTC());
return DateTime.parse(dateTime,formatter);
}
Imports used :
import org.joda.time.DateTime;
import org.joda.time.chrono.ISOChronology;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.joda.time.format.DateTimeParser;
I want my code to accept 2 different input forms(with or without milliseconds) and returns one DateTime without milliseconds.
Examples:
input can be:
2020-10-01T12:05:22.458-04:00
2020-10-01T12:05:22-04:00
Output:
2020-10-01T12:05:22-04:00
Any help on this will be greatly appreciated. Thanks!
You are reinventing the ISO_ZONED_DATE_TIME.
For this format, milliseconds are already optional. You only have to truncate them when present, to get your desired result. The format is even the standard, so the code is as simple as:
String[] samples = {
"2020-10-01T12:05:22.458-04:00",
"2020-10-01T12:05:22-04:00",
};
for(String s: samples) {
ZonedDateTime parsed = ZonedDateTime.parse(s).with(ChronoField.MILLI_OF_SECOND, 0);
System.out.println(parsed);
}
2020-10-01T12:05:22-04:00
2020-10-01T12:05:22-04:00
Note that I used MILLI_OF_SECOND to make the solution more intuitive regarding your task of removing the milliseconds. Actually, milliseconds are just nanoseconds with a lower precision, so you could use the even simpler ZonedDateTime.parse(s).withNano(0), once it has been understood.
Or, as suggested by Ole V.V., ZonedDateTime.parse(s).truncatedTo(ChronoUnit.SECONDS), which might be even easier to grasp.
Related
I will receive an string(with time and date) from the frontend. The string format is this "2021-08-16T23:15:00.000Z". I intend to declare a moment object with the input string, along with a specific timezone(other than the local one).
import moment from "moment";
import "moment-timezone";
// The input string I receive from the frontend.
let strTime = "2021-08-16T23:15:00.000Z";
console.log(strTime); //2021-08-16T23:15:00.000Z
let time = moment.tz(strTime, "YYYY-MM-DDTHH:mm:ss.SSSZ","America/Boise");
console.log(time); // Moment<2021-08-16T17:15:00-06:00>, undesired value
let UTCtime = moment.utc(time);
console.log(UTCtime);
As far as what I understood from this question, console.log(time) should output a moment object of time 23:15:00, but with timezone "America/Boise".
What I intend is time to have the same time i.e "23:15:00.000", with "America/Boise" as timezone.
So that when I later convert that time to UTC, I need to get the right value w.r.t the timezone "America/Boise" and not my local timezone. How can I do this.
I figured out a solution.
const momenttz = require("moment-timezone");
const moment = require("moment");
// The input string I receive from the frontend.
let strTime = "2021-08-16T23:15:00.000Z";
console.log(strTime); //2021-08-16T23:15:00.000Z
let time = moment.utc(strTime);
time.tz("America/Boise", true);
console.log(time.tz());
console.log(time); // Moment<2021-08-16T23:15:00-06:00>, desired value
let UTCtime = moment.utc(time);
console.log(UTCtime); // Moment<2021-08-17T05:15:00Z>
In the above code, at console.log(time),time has the value "23:15:00.000" with required timezone "America/Boise". This makes it possible for you to get the right value , when you later convert it to UTC.
This is made possible by passing an optional second parameter to .tz mutator of moment-timezone as true which changes only the timezone (and its corresponding offset), and does not affect the time value.
time.tz(timezone, true);
A sample example of using this is given in the answer code above.
You can read more about it here in the Moment Timezone Documentation
My application should be able to parse date ignoring timezone (I always know for sure that it is UTC). The problem is that the date might come in both following forms -
2017-09-11T12:44:07.793Z
0001-01-01T00:00:00
I can parse the first one using LocalDateTime, and the second one using Instant class. Is there a way to do that using a single mechanism?
P.S. I'm trying to avoid hardcoding Z at the end of the input string
If the Z offset is optional, you can use a java.time.format.DateTimeFormatterBuilder with an optional section:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter
.toFormatter();
Then you can use the parseBest method, with a list of TemporalQuery's that tries to create the correspondent object. Then you check the return type and act accordingly:
Instant instant = null;
// tries to create Instant, and if it fails, try a LocalDateTime
TemporalAccessor parsed = fmt.parseBest("2017-09-11T12:44:07.793Z", Instant::from, LocalDateTime::from);
if (parsed instanceof Instant) {
instant = (Instant) parsed;
} else if (parsed instanceof LocalDateTime) {
// convert LocalDateTime to UTC instant
instant = ((LocalDateTime) parsed).atOffset(ZoneOffset.UTC).toInstant();
}
System.out.println(instant); // 2017-09-11T12:44:07.793Z
Running with the second input (0001-01-01T00:00:00) produces the Instant equivalent to 0001-01-01T00:00:00Z.
In the example above, I used just Instant::from and LocalDateTime::from, so the formatter tries to first create an Instant. If it's not possible, then it tries to create a LocalDateTime. You can add as many types you want to that list (for example, I could add ZonedDateTime::from, and if a ZonedDateTime is created, I could just convert to Instant using toInstant() method).
As you know for sure that the input is always in UTC, you can also set it directly in the formatter:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter with UTC
.toFormatter().withZone(ZoneOffset.UTC);
So you can parse it directly to Instant:
System.out.println(Instant.from(fmt.parse("2017-09-11T12:44:07.793Z"))); // 2017-09-11T12:44:07.793Z
System.out.println(Instant.from(fmt.parse("0001-01-01T00:00:00"))); // 0001-01-01T00:00:00Z
You can "parseBest", like this:
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[Z]");
Temporal parsed = parser.parseBest(inputString, Instant::from, LocalDateTime::from);
Then you should check what did get parsed, and act accordingly.
The parseBest method will work with any type of TemporalQuery, including most of from methods available on java.time classes. So you can lengthen that list with LocalDate.from, for example.
You can also use that method and lambdas to coerse parse results to the type you want without having instanceof checks that are external for result resolution (although not without one cast):
Instant parsed = (Instant) parser.parseBest(inputString,
Instant::from,
interResult -> LocalDateTime.from(interResult).atZone(ZoneOffset.UTC).toInstant())
Notice that second option uses lambda that converts LocalDateTime to ZonedDateTime and then to Instant, so the parse results are always coersed to Instant.
I have an issue with date.In my Model class I have used DateTime property(I used Code First), for transferring json data from action to another action I use Jquery ($.ajax), my date convert in this format, I think it milliseconds:
/Date(1188594000000)/
I tryed to convert it using js, not working:
var date = new Date(mydate);
/Date(1188594000000)/ is a string and the long numbers inside the brackets are the milliseconds since the beginning of the unix epoch time. You cannot pass that(the string as it is) to Date constructor. If you want to generate a datetime object from that value, you should remove the first 6 characters (/Date() and pass the milliseconds only
var mydate='/Date(1188594000000)/';
var dateVal= parseInt(mydate.substr(6));
var dateObj= new Date(dateVal);
console.log(dateObj);
The statement mydate.substr(6) will return a string value like "1188594000000)/" and passing this to parseInt method returns the number 1188594000000 which can be safely passed to the Date constructor.
I need to get number of current month instead of getting its name:
void main()
{
SysTime dt = Clock.currTime();
writeln(dt.month);
}
The output is:
oct
but I need 10. How I can get it? I found only one solution cast it to int, but is there any better way, or it's ok?
Use std.conv.to() for converting types.
This seems to work:
import std.conv;
import std.datetime;
import std.stdio;
void main()
{
SysTime dt = Clock.currTime();
writeln(dt.month.to!ushort);
}
10
If you just need it for printing then use writefln like below.
writefln("%d", dt.month);
If you need to use the number then the to template can be used, which in general should be used for conversions.
writeln(dt.month.to!size_t);
// or ...
writeln(to!size_t(dt.month));
Ultimately you can also cast it.
writeln(cast(size_t)dt.month);
There is no need for explicit conversion as the Month enum's type is int by default (check more about enums).
import std.datetime;
// Month is an enum - http://dlang.org/phobos/std_datetime.html#.Month
Month month = Clock.currTime().month;
int monthnum = 0 + month; // works
Literally the inverse of this question, is there an easy way to get a .Net DateTime from an IronPython datetime?
Clearly, one could
Output a string and parse it or
Dump all the date parts into a DateTime constructor
but those are both messy. This doesn't work either:
pydate = datetime.datetime.now()
csharp = DateTime(pydate) # Crashes, because .Net wants a 'long' for Ticks
Is there an easy cast or a short way to get the Ticks that .Net wants?
I was fairly certain a direct conversion was already allowed, but I was wrong. I added it in 31f5c88 but that won't be available until (currently unscheduled) 2.7.6.
In the meantime the best way would be to use the timetuple method to get the parts:
dt = datetime.now()
d = DateTime(*dt.timetuple()[:6])
# For UTC times, you need to pass 'kind' as a kwarg
# because of Python's rules around using * unpacking
udt = datetime.now()
ud = DateTime(*udt.timetuple()[:6], kind=DateTimeKind.Utc)
Now that 2.7.6 has been released, you can use clr.Convert to make an explicit cast, if needed. There could be better ways to do this, but I'm stealing this one from Jeff Hardy's commit.
>>> from System import DateTime
>>> from datetime import datetime
>>> from clr import Convert
>>> now_py = datetime.now()
>>> now_py
datetime.datetime(2020, 1, 1, 18, 28, 34, 598000)
>>> Convert(now_py, DateTime)
<System.DateTime object at 0x00000000006C [1/1/2020 6:28:34 PM]>
>>> now_py == Convert(now_py, DateTime)
True
DateTime(pydate) still crashes.
Jeff's answer gets a DateTime to the second. If you want to stretch the precision to the millisecond, you can use something like this:
def cs_date(date):
return DateTime(*date.timetuple()[:6] + (date.microsecond/1000,))