I have a requirement where I have to extract the date and time displayed on the screen, which is in following format: 2021 Jul 12 # 06:30
And I have to compare this with a specific timezone to check whether they are equal or not.
Can anyone please help me with the way to handle this logic in Selenium Java (any version)?
Assuming you are retrieving the date time as a string, you can use a combination of ZonedDateTime and LocalDateTime as follows:
First we get your system zone and zoned datetime:
ZoneId timeZone = ZoneId.systemDefault();
LocalDateTime nowLocalDateTime = LocalDateTime.now();
ZonedDateTime nowZonedDateTime = ZonedDateTime.of(localDateTime, timeZone);
Then we define the pattern using formatter, and use it to format the example string to a ZonedDateTime object:
DateTimeFormatter exampleFormatter = DateTimeFormatter.ofPattern("yyyy MMM dd # HH:mm");
String example = "2021 Jul 12 # 06:30";
ZonedDateTime exampleZonedDateTime = LocalDateTime.parse(example, formatter).atZone(timeZone);
Here, I used the system timezone but you can change this to the zone you like assuming you know the time zone of the example.
This way we can compare exampleZonedDateTime with nowZoned DateTime where:
nowZonedDateTime holds the systems current defined timezone
exampleZonedDateTime holds the Zoned date time you want to compare with.
Also you can convert both to LocalDateTime objects using .toLocalDateTime() method in the ZonedDateTime class.
Related
This question already has answers here:
How to display time amount to user?
(1 answer)
Java 8 epoch-millis time stamp to formatted date, how?
(3 answers)
Closed 2 years ago.
I have a value in miliseconds 1601626934449
Which generated via https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#currentTimeMillis()
but can I somehow be able to get time in human readable format, or in brief I need to be able to know what the value in miliseconds 1601626934449 is ?
Use java.time on Java 8 or higher. Using that, it's easy to reach your goal.
You basically create an Instant from the epoch milliseconds (which represent a moment in time), make it a ZonedDateTime by applying a ZoneId (my system's default in the following example) and then either format the output String by a built-in DateTimeFormatter or by creating a custom one with a desired pattern to make it as human-readable as required.
Here's an example:
public static void main(String[] args) {
// your example millis
long currentMillis = 1601626934449L;
// create an instant from those millis
Instant instant = Instant.ofEpochMilli(currentMillis);
// use that instant and a time zone in order to get a suitable datetime object
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
// then print the (implicitly called) toString() method of it
System.out.println(currentMillis + " is " + zdt);
// or create a different human-readable formatting by means of a custom formatter
System.out.println(
zdt.format(
DateTimeFormatter.ofPattern(
"EEEE, dd. 'of' MMMM uuuu 'at' HH:mm:ss 'o''clock in' VV 'with an offset of' xxx 'hours'",
Locale.ENGLISH
)
)
);
}
which outputs (on my system)
1601626934449 is 2020-10-02T10:22:14.449+02:00[Europe/Berlin]
Friday, 02. of October 2020 at 10:22:14 o'clock in Europe/Berlin with an offset of +02:00 hours
You can convert millis into LocalDateTime to store time
long millis = System.currentTimeMillis();
LocalDateTime datetime = Instant.ofEpochMilli(millis)
.atZone(ZoneId.systemDefault()).toLocalDateTime();
Then you can print your data using toString() or your desire format using DateTimeFormatter.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS");
System.out.println(datetime.format(formatter));
Output: 2020-10-02 18:39:54.609
You can create a Date object and use it to get all the information you need:
https://docs.oracle.com/javase/7/docs/api/java/util/Date.html#Date(long)
I have been parsing dates in the below formats. I maintain an array of these formats and parse every date string in all these formats.
The code I used was -
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
simpleDateFormat.setTimeZone(timeZone); //timeZone is a java.util.TimeZone object
Date date = simpleDateFormat.parse(dateString);
Now I want to parse yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX format as well but using SimpleDateFormat the 6 digit microseconds are not considered. So I looked into java.time package.
To parse yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX formats I will be needing OffsetDateTime class and for other formats, I need ZonedDateTime class. The format will be set in DateTimeFormatter class.
Is there a way to use a single class like SimpleDateFormat to pass all the formats?
Since your Java 8 doesn’t behave as would be reasonably expected, I suggest that a workaround is trying to parse without zone first. If a zone or an offset is parsed from the string, this will be used. If the parsing without zone fails, try with a zone. The following method does that:
private static void parseAndPrint(String formatPattern, String dateTimeString) {
// Try parsing without zone first
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern);
Instant parsedInstant;
try {
parsedInstant = formatter.parse(dateTimeString, Instant::from);
} catch (DateTimeParseException dtpe) {
// Try parsing with zone
ZoneId defaultZone = ZoneId.of("Asia/Calcutta");
formatter = formatter.withZone(defaultZone);
parsedInstant = formatter.parse(dateTimeString, Instant::from);
}
System.out.println("Parsed instant: " + parsedInstant);
}
Let’s try it:
parseAndPrint("yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX", "2018-10-22T02:17:58.717853Z");
parseAndPrint("yyyy-MM-dd'T'HH:mm:ss.SSSSSS", "2018-10-22T02:17:58.717853");
parseAndPrint("EEE MMM d HH:mm:ss zzz yyyy", "Mon Oct 22 02:17:58 CEST 2018");
Output on Java 8 is:
Parsed instant: 2018-10-22T02:17:58.717853Z
Parsed instant: 2018-10-21T20:47:58.717853Z
Parsed instant: 2018-10-22T00:17:58Z
The first example has an offset in the string and the last a time zone abbreviation in the string, and in both cases are these respected: the instant printed has adjusted the time into UTC (since an Instant always prints in UTC, its toString method makes sure). The middle example has got neither offset nor time zone in the string, so uses the default time zone of Asia/Calcutta specified in the method.
That said, parsing a three or four letter time zone abbreviation like CEST is a dangerous and discouraged practice since the abbreviations are often ambiguous. I included the example for demonstration only.
Is there a way to use a single class…?
I have used Instant for all cases, so yes there is a way to use just one class. The limitation is that you do not know afterward whether any time zone or offset was in the string nor what it was. You didn’t know when you were using SimpleDateFormat and Date either, so I figured it was OK?
A bug in Java 8?
The results from your demonstration on REX tester are disappointing and wrong and do not agree with the results I got on Java 11. It seems to me that you have been hit by a bug in Java 8, possibly this one: Parsing with DateTimeFormatter.withZone does not behave as described in javadocs.
This question already has answers here:
Parsing ISO-8601 DateTime with offset with colon in Java
(4 answers)
Closed 5 years ago.
how to parse yyyy-mm-ddThh:mm:ssZ into my specific timezone and only display the time?
For example:
from 2017-11-22T22:00:00Z
to 2017-11-22 23:00
Because my timezone is one hour ahead of the timezone that the first string was from, I hope you understand!
If using Java 8, you can parse it as an Instant and then convert it to a ZonedDateTime in the time zone you need. You can then get the local time from the ZonedDateTime.
Instant instant = Instant.parse("2017-11-22T22:00:00Z");
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(zdt.toLocalTime());
You can also specify a specific Zone ID other than the system default. To see the available Zone IDs to choose from, use ZoneId.getAvailableZoneIds())
Using ZonedDateTime will handle daylight savings. If you simply need a static hour offset, you can convert it to an OffsetDateTime instead of the ZonedDateTime.
First, parse your string as an Instant, then convert that to a ZoneDateTime in the desired zone; from that, you can obtain the LocalTime
LocalTime time = Instant.parse(str).atZone(ZoneId.systemDefault()).toLocalTime();
Java DateFormater
String date = "2011-01-18 00:00:00";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyy-mm-dd hh:mm:ss");
Date parsedDate = dateFormat.parse(date);
Depending on a request url, I have to convert a Date to different requested time zone and return date and time as String. I am using java 8 with spring boot and mongo 3.2
So inside the service method, I first set the time zone as below,
TimeZone.setDefault(TimeZone.getTimeZone(TIME_ZONE))
But I notice, it will change the time zone of whole java application. So even the method exit, the time zone would be remain the time zone I set previously.
So instead setDefault method level, I set it specifically in the SimpleDateFormat as below,
(assignment is a Assignmet document class having java.util.Date as a property named assignmentEndDate which map to a mongodb collection. In mongo db assignmentEndDate is store as UTC)
java.text.DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy'T'HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone(timezone));
Date assignmentEndDate = assignment.getAssignmentEndDate();
formatter.format(assignmentEndDate);
This way it wont change the application level time zone. Is this the correct approach for such scenario?
Take advantage of new date time api included in Java 8.
ZoneId zoneId = ZoneId.of("America/Chicago");
You can start with Instant, a java util date equalivent.
Instant instant = Instant.now();
ZonedDateTime zonedDateTime = instant.atZone(zoneId);
Or
You can also start with
using ZonedDateTime
You can take datetime as LocalDateTime, time zone agnostic class and convert to ZonedDateTime.
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(zoneId);
You can easliy switch betweeen old date time classes & new time by accessing the helper methods on each of the new/old date time classes.
Change to java util date while saving to mongo database
//From ZonedDateTime to java util date.
Date oldDate = Date.from(zdt.toInstant());
//From Instant to java util date
Date oldDate = Date.from(instant);
//From Date to Instant.
Instant instant = date.toInstant();
All the new date time api have default formatter built into it.
//2007-12-03T10:15:30-06:00[America/Chicago]
String zonedDatetime = zonedDateTime.toString();
For specfic format you can always pass the DateTimeFormatter to the below method.
zonedDateTime.format(formatter)
I have the following date value 1995-12-31T23:59:59
but in order to parse this for a solr query I need it in the below format
1995-12-31T23:59:59Z
How can I parse this to get the added "Z" on the end in java 1.6 ?
The type must be java.util.date after the conversion - fyi
When I toString the date now and attempt to parse it with the SimpleDateFormat object it looks like this
"Mon Jan 01 00:00:00 CST 2001" - what is this format to convert it?
Use SimpleDateFormat:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date d = df.parse("1995-12-31T23:59:59Z");
System.out.println(d);
Put the 'Z' in single quotes to escape
"Z" is the time zone abbreviation for Zulu time zone i.e. UTC. If solr API accepts the date object, then you can just parse the date in the following way by setting preferred timezone:
SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateParser.setTimeZone(TimeZone.getTimeZone("Z"));
Date date = df.parse("1995-12-31T23:59:59");
If you need to convert it back to string then use the method provided by nsfyn55:
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
System.out.println(dateFormatter.format());
Avoid Old Date-Time Classes
You are using the old java.util.Date/.Calendar and SimpleDateFormat classes. Avoid them.
The Date class has the poor design choice of its toString applying a default time zone when generating a String. So it seems like it has a time zone when in fact it does not (except one buried underneath that is ignored for regular use). Confusing, yes. Avoid it.
java.time
Instead use java.time built into Java 8 and later.
First parse as a LocalDateTime without any time zone or offset.
LocalDateTime ldt = LocalDateTime.parse( "1995-12-31T23:59:59Z" );
Apply a time zone or offset-from-UTC to give this LocalDateTime meaning, to make it an actual moment on the timeline. You have to know, or ask, what time zone or offset was intended by this string as no indication was embedded. For this example, I will arbitrarily assume Québec.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );
Your desired output has a Z on the end, for Zulu which means UTC.
In java.time an Instant represents a moment on the timeline in UTC. You can extract an Instant from the ZonedDateTime.
Instant instant = zdt.toInstant();
The Instant class’ toString method generates a string in your desired format. That format is one of the standard ISO 8601 formats.
String output = instant.toString();
Half-Open
I happened to notice that your example value was trying to get the end of 1995. There is a better way to do such search or comparison criteria.
In date-time work, the best practice is called Half-Open where the beginning of a span of time is inclusive while the ending is exclusive. So a week starts on Monday and runs up to, but not including, the next Monday.
Defining a year means starting at the first moment of the first day of 1995 and running up to but not including the first moment of the first day of the following year, 1996. Searching for any values within that range is done not with a BETWEEN but as: ( someEvent >= firstMomentOf1995 AND someEvent < firstMomentOf1996 ) ( not <= ).