I'm trying to convert a Brazil local date to UTC format. I have developed my solution but I'm sure that it can be improved. I have been searching for others questions but without success.
My problem is that when I process the Date object with:
Instant endDateTime = questionDate.toInstant();
I receive a UTC date as "2017-11-16T00:00:00Z" but this should be Brazil local date (not correct because it has a trailing "Z") and when I try to convert to UTC, I receive the same output.
In another hand, if I use ZoneDateTime class and build the date with LocalDateTime object I lose the seconds in the output: "2017-11-16T02:00Z". This happens when I use:
LocalTime.of(hour, minutes, seconds);
I search into LocalTime class and I think this is because minutes or seconds are 0 but I'm not sure of it.
Problems of the solution:
The response hasn't seconds
I hope Java 8 has a set of functions to make this more simple and clear
Precondition:
I can't use Joda library
Result has to be OffsetDateTime class
Input: Date "2017-11-16"
Output: "2017-11-16T02:00:00Z"
This is my solution:
private static OffsetDateTime processDate(Date questionDate) {
Instant endDateTime = questionDate.toInstant();
ZoneId zoneId = ZoneId.of(ZONEID);
String [] date = endDateTime.toString().split("T");
LocalDateTime localDateTime = convertLocalTimeToUtc(date);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
ZonedDateTime utcDate = zonedDateTime.withZoneSameInstant(ZoneOffset.UTC);
return utcDate.toOffsetDateTime();
}
private static LocalDateTime convertLocalTimeToUtc(String[] dateFromCountry) {
LocalDate date = processDate(dateFromCountry[0]);
LocalTime time = processTime(dateFromCountry[1]);
return LocalDateTime.of(date, time);
}
private static LocalDate processDate(String dateFromCountry) {
String [] partsOfDate = dateFromCountry.split("-");
int year = Integer.parseInt(partsOfDate[0]);
int month = Integer.parseInt(partsOfDate[1]);
int day = Integer.parseInt(partsOfDate[2]);
return LocalDate.of(year, month, day);
}
private static LocalTime processTime(String dateFromCountry) {
String [] partsOfTime = dateFromCountry.split(":");
int hour = Integer.parseInt(partsOfTime[0]);
int minutes = Integer.parseInt(partsOfTime[1]);
int seconds = Integer.parseInt(partsOfTime[2].substring(0,1));
return LocalTime.of(hour,minutes,seconds);
}
If your input is a java.util.Date, you can get rid of all the string manipulation:
//simulate your input
Instant input = Instant.parse("2017-11-16T00:00:00Z");
Date d = Date.from(input);
//transformation code starts here
Instant instant = d.toInstant();
ZonedDateTime localInstant = instant.atZone(ZoneOffset.UTC);
ZonedDateTime sameLocalInBrazil = utcInstant.withZoneSameLocal(ZoneId.of("Brazil/East"));
OffsetDateTime sameInstantUtc = sameLocalInBrazil.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);
This return an OffsetDateTime with value 2017-11-16T02:00Z as you expect.
Note that an OffsetDateTime has no formatting - so the object does know that its seconds are set to 0 but the default toString method doesn't print them. If you want to print it with seconds, you can use a formatter:
//Formatting
System.out.println(sameInstantUtc.format(DateTimeFormatter.ISO_INSTANT));
which prints 2017-11-16T02:00:00Z
If your input is a java.sql.Date, you can use a slightly different strategy:
LocalDate d = sqlDate.toLocalDate();
ZonedDateTime localInstant = d.atStartOfDay(ZoneOffset.UTC);
The rest of the code would be the same.
Related
I have one date in format of date = "2022-07-03 10:09:19"
Need to get difference of months from Today date and time
You can leverage java.time library. Here is a sample code snippet:
import java.time.LocalDateTime
import java.time.temporal.ChronoUnit
val dateOld = "2022-07-03 10:09:19".replace(" ", "T")
val dateNew = "2022-11-03 10:09:19".replace(" ", "T")
val l1 = LocalDateTime.parse(dateOld)
val l2 = LocalDateTime.parse(dateNew)
val months = ChronoUnit.MONTHS.between(l1, l2)
For calculating from current time you can use:
val date = "2021-07-03 10:09:19".replace(" ", "T")
val l1 = LocalDateTime.parse(date)
val l3 = LocalDateTime.now()
val months = ChronoUnit.MONTHS.between(l1, l3)
Hope this helps !!
Use ChronoUnit to solve it
import java.time.LocalDateTime
import java.time.temporal.ChronoUnit
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime previousDate = LocalDateTime.parse(date, formatter);
LocalDateTime now = LocalDateTime.now();
long diffMonths = ChronoUnit.MONTHS.between(now, previousDate);
Use java.time if possible
You can parse the datetime String, add a time zone and take the current day or moment in the same time zone. Then you can extract the date and calculate the Period.between those two.
Here's an example in Java:
public static void main(String[] args) {
// example input
String someTime = "2022-07-03 10:09:19";
// prepare a formatter that can parse such a String
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
// prepare the time zone
// (I will use UTC, but the zone depends on the one of the input)
ZoneId utc = ZoneId.of("UTC");
// parse the String, apply the zone and directly extract the date
LocalDate then = LocalDateTime.parse(someTime, dtf)
.atZone(utc)
.toLocalDate();
// get the date of today in the zone
LocalDate today = LocalDate.now(utc);
// calculate the period between the two dates
long months = ChronoUnit.MONTHS.between(then, today);
// prepare some meaningful message to be printed
String msg = String.format(
"The difference in months between %s (then) and %s (today) is %d months",
then, today, months);
// and actually print it
System.out.println(msg);
}
Output:
The difference in months between 2022-07-03 (then) and 2022-08-03 (today) is 1 months
Parse the given date to an instance of java.time.LocalDateTime, then you can get an instance of java.time.Period for the two dates, and from that, you can get the months.
In Java:
final DateTimeFormatter parser = … // An appropriate parser for the given format
final var otherDate = LocalDateTime.parse( dateString, parser );
final var deltaPeriod = Period.between( LocalDateTime.now(), otherDate );
final var result = deltaPeriod.getYears() * 12 + deltaPeriod.getMonths(); // or use Period::toTotalMonths()
I have to convert
"fromTime" : "04-10-2021"`
to
"fromTime" : "2021-10-04T00:00:00.000"
and
"toTime" : "06-10-2021"
to
"toTime" : "2021-10-06T23:59:59.000"
in java . Help please!
Generally speaking, you really want to avoid representing date/time as String where ever possible.
Displaying date/time values to the user should be done in styles that respect their localisation and transmitting date/time values using JSON or XML should use common/standardised formats. This reduces a LOT of issues (don't even get me started)
For example, had I the choice, I would prefer to use ISO_LOCAL_DATE (uuuu-MM-dd) and ISO_LOCAL_DATE_TIME (uuuu-MM-dd'T'HH:mm:ss). I'm already worried about the lack of time zone information 😱
A "simple" approach might be to do something like...
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-MM-uuuu");
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("dd-MM-uuuu.SSS");
LocalDateTime locatDateTime = LocalDate
.parse("04-10-2021", dateFormatter)
.atTime(0, 0, 0, 0);
String dateAndTime = locatDateTime.format(timeFormatter);
System.out.println(dateAndTime);
locatDateTime = LocalDate
.parse("04-10-2021", dateFormatter)
.atTime(23, 59, 59, 0);
dateAndTime = locatDateTime.format(timeFormatter);
System.out.println(dateAndTime);
Basically...
Parse the date value through a DateTimeFormatter using a matching format patten
Convert the LocalDate to a LocalDateTime by passing in the values we want to use
Format the LocalDateTime through a DateTimeFormatter to the desired format
which prints...
04-10-2021T00:00:00.000
06-10-2021T23:59:59.000
See:
The date/time trail
Introduction to the Java 8 Date/Time API
for more details
Now, if all you really want to do, is make it "start of" and "end of" day, you might be able to use...
LocalDateTime startOfDay = LocalDate
.parse("04-10-2021", dateFormatter)
.atStartOfDay();
LocalDateTime endOfDay = LocalDate
.parse("06-10-2021", dateFormatter)
.plusDays(1)
.atStartOfDay()
.minusSeconds(1);
Right about now, I'd be starting a utility class of some kind which had a method which could take a date String (and possibly an optional format) and generate a LocalDate and then another method which could take LocalDate which could convert it to a LocalDateTime at either the startOfDay or endOfDay
You have to do these steps:
create a DateTimeFormatter for dd-MM-yyyy
parse the date with LocalDate.parse with atTime
create a DateTimeFormatter for yyyy-MM-dd'T'HH:mm:ss.SSS
format the date in order to have the final result
public String changeFormatDate(String date, int hour, int minute, int second, int nanoOfSecond) {
DateTimeFormatter formatterFrom = DateTimeFormatter.ofPattern("dd-MM-yyyy"); // 1
LocalDateTime localDateTimeFrom = LocalDate.parse(date, formatterFrom).atTime(hour, minute, second, nanoOfSecond); // 2
DateTimeFormatter formatterTo = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS"); // 3
return localDateTimeFrom.format(formatterTo); //4
}
Call example:
String fromTime = changeFormatDate("04-10-2021", 0, 0, 0, 0);
String toTime = changeFormatDate("06-10-2021", 23, 59, 59, 999999999);
Here's an example using java.time:
public static void main(String[] args) {
// input dates / days
String fromDate = "04-10-2021";
String toDate = "06-10-2021";
// prepare the times of day
LocalTime startOfDay = LocalTime.MIN; // 00:00:00.000
LocalTime endOfDay = LocalTime.of(23, 59, 59); // 23:59:59.000
// create an object that takes care of parsing the expected format
DateTimeFormatter customDateParser = DateTimeFormatter.ofPattern("dd-MM-uuuu");
// then parse the dates using the formatter / parser
LocalDate fromDay = LocalDate.parse(fromDate, customDateParser);
LocalDate toDay = LocalDate.parse(toDate, customDateParser);
// then concatenate the parsed dates with the prepared times of day
LocalDateTime fromTime = LocalDateTime.of(fromDay, startOfDay);
LocalDateTime toTime = LocalDateTime.of(toDay, endOfDay);
// finally define a formatter for the String output of the LocalDateTimes
DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS");
// and print their toString() methods
System.out.println("from " + fromTime.format(customFormatter)
+ " to " + toTime.format(customFormatter));
}
from 2021-10-04T00:00:00.000 to 2021-10-06T23:59:59.000
I want to convert the given HH:mm from UTC to different time zones.
String myDateString = "02:30";
LocalTime localTime = LocalTime.parse(myDateString, DateTimeFormatter.ofPattern("HH:mm"));
int hour = localTime.get(ChronoField.CLOCK_HOUR_OF_DAY);
int minute = localTime.get(ChronoField.MINUTE_OF_HOUR);
int second = localTime.get(ChronoField.SECOND_OF_MINUTE);
System.out.println("UTC Time is "+ hour + ":" + minute);
Calendar pstTime = new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"));
hour = pstTime.get(hour);
minute = pstTime.get(minute);
getting error with this. any help appreciated.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
30
As already said, a time zone without day part misses information considering DST.
So it is:
String myDateString = "02:30";
LocalTime localTime = LocalTime.parse(myDateString,
DateTimeFormatter.ofPattern("HH:mm"));
LocalDateTime localDateTime = localTime.atDate(LocalDate.now());
System.out.println("localDateTime: " + localDateTime);
ZonedDateTime zonedDateTimeUTC = localDateTime.atZone(ZoneId.of("UTC"));
System.out.println("zonedDateTimeUTC: " + zonedDateTimeUTC);
ZonedDateTime zonedDateTimePST = zonedDateTimeUTC.withZoneSameInstant(
ZoneId.of("America/Los_Angeles"));
System.out.println("zonedDateTimePST: " + zonedDateTimePST);
int hour = zonedDateTimePST.getHour();
int minute = zonedDateTimePST.getMinute();
int second = zonedDateTimePST.getSecond();
There is no need for the old Calendar class.
I think you should specify date too. For that problem you can use this block of code
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter
.ofPattern("MM/dd/yyyy'T'HH:mm z");
String inputValue = "08/03/2020T15:20 UTC";
ZonedDateTime zdtInstanceAtOffset = ZonedDateTime.parse(inputValue, DATE_TIME_FORMATTER);
ZonedDateTime zonedDateTime = zdtInstanceAtOffset.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));
System.out.println(zonedDateTime);
Without a date, you can convert a time, given for one timezone, to another timezone only by adding/subtracting the time difference between the source timezone and the target timezone to/from the given time.
The problem with this approach is, that the time difference between timezones is not constant over the year, when it is identified by "region/location" (like "America/Los Angeles"). If you use "EST" or "GMT" or "CET" (sometimes referred to as "zone times") instead, the differences would be stable – but you are still inaccurate: several timezones will have two zone times, depending on the time in the year …
You can use the java.time.ZonedDateTime class for this and the method withZoneSameInstant(ZoneId zone) which returns a copy of the datetime in the specified zone.
Here is an example if your input time is in UTC timezone. To change the zone of the input time change Zone inputZone to ZoneId.of("<your timezone>");
public static void main(String[] args) {
String timeString = "02:30";
// Change this to the zone of the input time
ZoneId inputZone = ZoneId.of("UTC");
// Parse your input into time
LocalTime time = LocalTime.parse(timeString);
// Add current date to the time, you can add custom date using LocalDate.of(int year, int month, int dayOfMonth)
LocalDateTime localDateTime = time.atDate(LocalDate.now());
// Declare zoned date time with input zone specified
ZonedDateTime zonedDateTime = localDateTime.atZone(inputZone);
// Declare zones you will use
ZoneId myZone = ZoneId.systemDefault();
ZoneId utcZone = ZoneId.of("UTC");
ZoneId nyZone = ZoneId.of("America/New_York");
ZoneId tokyoZone = ZoneId.of("Asia/Tokyo");
// Get times in different timezones
ZonedDateTime myDateTime = zonedDateTime.withZoneSameInstant(myZone);
ZonedDateTime utcDateTime = zonedDateTime.withZoneSameInstant(utcZone);
ZonedDateTime nyDateTime = zonedDateTime.withZoneSameInstant(nyZone);
ZonedDateTime tokyoDateTime = zonedDateTime.withZoneSameInstant(tokyoZone);
// Print the times in different timezones
System.out.println("My Timezone: " + myDateTime);
System.out.println("UTC: " + utcDateTime);
System.out.println("NY: " + nyDateTime);
System.out.println("Tokyo: " + tokyoDateTime);
// Print without the offset
System.out.println("My Timezone: " + myDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
System.out.println("UTC: " + utcDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
System.out.println("NY: " + nyDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
System.out.println("Tokyo: " + tokyoDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
This code will generate the following output:
My Timezone: 2020-03-11T03:30+01:00[Europe/Zagreb]
UTC: 2020-03-11T02:30Z[UTC]
NY: 2020-03-10T22:30-04:00[America/New_York]
Tokyo: 2020-03-11T11:30+09:00[Asia/Tokyo]
My Timezone: 2020-03-11T03:30:00
UTC: 2020-03-11T02:30:00
NY: 2020-03-10T22:30:00
Tokyo: 2020-03-11T11:30:00
EDIT: I have edited my question to include more information, I have tried many ways to do this already, asking a question on StackOverflow is usually my last resort. Any help is greatly appreciated.
I have a date (which is a Timestamp object) in a format of YYYYMMDDHHMMSS (e.g. 20140430193247). This is sent from my services to the front end which displays it in the format: date:'dd/MM/yyyy' using AngularJS.
How can I convert this into Epoch/Unix time?
I have tried the duplicate question that is linked to this, what I get returned is a different date.
I have also tried the following:
A:
//_time == 20140430193247
return _time.getTime()/1000; // returns 20140430193 - INCORRECT
B:
return _time.getTime(); // returns 20140430193247 (Frontend: 23/03/2608) - INCORRECT
C:
Date date = new Date();
//_time = 20140501143245 (i.e. 05/01/2014 14:32:45)
String str = _time.toString();
System.out.println("Time string is " + str);
//Prints: Time string is 2608-03-24 15:39:03.245 meaning _time.toString() cannot be used
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
try {
date = df.parse(str);
} catch (ParseException e) {
}
return date; // returns 20140501143245 - INCORRECT
D:
date = new java.sql.Date(_time.getTime());
return date; // returns 2608-03-24 - INCORRECT
The following shows the todays date correctly:
Date date = new Date();
return date; // returns 1398939384523 (Frontend: 01/05/2014)
Thanks
I got the answer after quite a while of trying different ways. The solution was pretty simple - to parse the time to a string as toString() didn't work.
Date date;
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
try {
date = df.parse(String.valueOf(_time.getTime()));
} catch (ParseException e) {
throw new RuntimeException("Failed to parse date: ", e);
}
return date.getTime();
tl;dr
LocalDateTime
.parse(
"20140430193247" ,
DateTimeFormatter.ofPattern( "uuuuMMddHHmmss" )
)
.atOffset(
ZoneOffset.UTC
)
.toEpochSecond()
java.time
Parse your input string as a LocalDateTime as it lacks an indicator of offset-from-UTC or time zone.
String input = "20140430193247" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMddHHmmss" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
Now we have a date with time-of-day, around half-past 7 PM on April 30 of 2014. But we lack the context of offset/zone. So we do not know if this was 7 PM in Tokyo Japan or 7 PM in Toledo Ohio US, two different moments that happened several hours apart.
To determine a moment, you must know the intended offset/zone.
If you know for certain that an offset of zero, or UTC itself, was intended, apply the constant ZoneOffset.UTC to get an OffsetDateTime.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;
How can I convert this into Epoch/Unix time?
Do you mean a count of seconds or milliseconds since the first moment of 1970 in UTC?
For a count of whole seconds since 1970-01-01T00:00Z, interrogate the OffsetDateTime object.
long secondsSinceEpoch = odt.toEpochSecond() ;
For milliseconds, extract a Instant object. An Instant represents a moment in UTC, and is the basic building-block class of java.time. Then interrogate for the count.
Instant instant = odt.toInstant() ;
long millisSinceEpoch = instant.toEpochMilli() ;
there is a form having a drop down for country ,user will select the country ,then there is a drop down for time zone ,user will select the time zone which are available in country selected by the user.Then user will enter the local date( eg: 26-Dec-2014) and time( 23:11)(24 hours time) this entered date and time is for the selected country and time zone.
now i have to convert this date and time to GMT time zone. how can i do this using joda time
how the daylight saving time(DST) will be calculate?
i have made a function which accepts the parameters as from time zone,to time zone,date
public static String convertTimeZones( String fromTimeZoneString,
String toTimeZoneString, String fromDateTime) {
DateTimeZone fromTimeZone = DateTimeZone.forID(fromTimeZoneString);
DateTimeZone toTimeZone = DateTimeZone.forID(toTimeZoneString);
DateTime dateTime = new DateTime(fromDateTime, fromTimeZone);
DateTimeFormatter outputFormatter
= DateTimeFormat.forPattern("dd-MMM-yyyy HH:mm").withZone(toTimeZone);
return outputFormatter.print(dateTime);
}
i want to pass the date to this function in a format (24-Feb-2014 12:34) but it is not taking this format
//so we can get the local date
//UTC = true, translate from UTC time to local
//UTC = false, translate from local to UTC
public static String formatUTCToLocalAndBackTime(String datetime, boolean UTC) {
String returnTimeDate = "";
DateTime dtUTC = null;
DateTimeZone timezone = DateTimeZone.getDefault();
DateTimeFormatter formatDT = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime dateDateTime1 = formatDT.parseDateTime(datetime);
DateTime now = new DateTime();
DateTime nowUTC = new LocalDateTime(now).toDateTime(DateTimeZone.UTC);
long instant = now.getMillis();
long instantUTC = nowUTC.getMillis();
long offset = instantUTC - instant;
if (UTC) {
//convert to local time
dtUTC = dateDateTime1.withZoneRetainFields(DateTimeZone.UTC);
//dtUTC = dateDateTime1.toDateTime(timezone);
dtUTC = dtUTC.plusMillis((int) offset);
} else {
//convert to UTC time
dtUTC = dateDateTime1.withZoneRetainFields(timezone);
dtUTC = dtUTC.minusMillis((int) offset);
}
returnTimeDate = dtUTC.toString(formatDT);
return returnTimeDate;
}
Java time api is better compared to joda time api when it comes to various timezones, specially with day light savings
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
LocalDateTime start = LocalDateTime.of(2021, 02, 25, 14, 25, 00);
ZoneId zone = ZoneId.of("Asia/Singapore");
start = start.atZone(zone).withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime();