Using joda, how do you format a UTC+/-n time, to "wall time" to be displayed to the user:
From (UTC+/-n):
2015-05-15T03:28:49.523-04:00
To (EST) Wall:
2015-05-14 23:22:44
Update (1)
Please consider the following code. We need to use timestamp
for writes to and from the DB in UTC. With that in mind:
DateTimeZone.setDefault(DateTimeZone.UTC);
LocalDateTime utcDate = new LocalDateTime();
DateTimeZone utcTZ = DateTimeZone.forTimeZone(TimeZone.getTimeZone("ETC/UTC"));
DateTimeZone localTZ = DateTimeZone.forTimeZone(TimeZone.getTimeZone("America/Montreal"));
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
fmt.withZone(localTZ);
DateTime localDateTime = utcDate.toDateTime(localTZ);
DateTime utcDateTime = localDateTime.toDateTime(utcTZ);
Timestamp u = new Timestamp(utcDateTime.getMillis());
System.out.println("UTC Time: " + u);
LocalDateTime date = new LocalDateTime(u);
DateTime srcDateTime = date.toDateTime(utcTZ);
DateTime dstDateTime = srcDateTime.toDateTime(localTZ);
System.out.println("UTC+/- Time: " + dstDateTime.toString());
DateTime dateTimeInTargetTimezone = dstDateTime.withZone(localTZ);
System.out.println("Wall Time: " + dateTimeInTargetTimezone.toString("yyy-MM-dd HH:mm:ss"));
Now, when extracting the UTC time from the DB in a Timestamp object, we need
to display the time to the end user in a "Wall/Funeral Time", whatever you want to call it, in their TZ.
Output
UTC Time: 2015-05-15 20:03:47.561 "Good"
UTC+/- Time: 2015-05-15T20:03:47.561-04:00 "Good"
Wall Time: 2015-05-15 20:03:47 "No! No! No! Danger! We'll be late!"
What in the name! Do I have to do to get dstDateTime to equal the time I see on my wall (ie, 2015-05-15 4:03:47).
Update (2)
Got rid of Timestamp:
DateTimeZone utcTZ = DateTimeZone.forTimeZone(TimeZone.getTimeZone("ETC/UTC"));
DateTimeZone localTZ = DateTimeZone.forTimeZone(TimeZone.getTimeZone("America/Montreal"));
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyy-MM-dd HH:mm:ss");
LocalDateTime utcDate = new LocalDateTime(utcTZ);
DateTime utcDateTime = utcDate.toDateTime(utcTZ);
System.out.println("UTC Time: " + utcDateTime);
DateTime dstDateTime = utcDateTime.toDateTime(localTZ);
System.out.println("Unformated Wall Time: " + dstDateTime);
System.out.println("Wall Time: " + dstDateTime.toString(fmt));
Output
UTC Time: 2015-05-20T14:09:28.469Z
Unformated Wall Time: 2015-05-20T10:09:28.469-04:00
Wall Time: 2015-05-20 10:09:28
Everything looks perfect however, when I try to right the UTZ date to the DB,
I need to convert to Timestamp (ie, new Timestamp(o.getOrderDate().getMillis())), and it obviously rights the local time to the DB, and not the UTC Zulu time that I need.
Thanks in Advance,
Nick.
#Nick
I'm not sure if I understood your question correctly but you can try this:
//sample input
String timestamp = "2015-05-15T03:28:49.523-04:00";
//format to parse
DateTimeFormatter dateTimeF = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
//parse to local date time
LocalDateTime dateTime = dateTimeF.parseLocalDateTime(timestamp).minusHours(4);
//output here minus 4 hours
System.out.println(dateTime);
You can improve your implementation from my sample code above and make the offset hours more dynamic but so far this code provides the result as you mentioned in your example.
Goodluck!
Just use the DateTime.withZone method to change the timezone:
#Test
public void change_timezone() {
String input = "2015-05-15T03:28:49.523-04:00";
DateTimeZone targetTimeZone = DateTimeZone.forID("Europe/London");
DateTime dateTime = DateTime.parse(input);
DateTime dateTimeInTargetTimezone = dateTime.withZone(targetTimeZone);
assertThat(dateTimeInTargetTimezone.toString("yyy-MM-dd HH:mm:ss"),
equalTo("2015-05-15 08:28:49"));
}
Related
First off I'm new in this incredible community. This is an amazing site. I'm happy to be part finally.
Every day I have to insert yesterday's data in the DB. For example, today May 22, I have to insert the data of the 21st from 00:00:00 to 23:59:59 in epoch time.
So far I get the epoch time from today with
long now = Instant.now().toEpochMilli();
How could I get yesterday's epoch time? and store the range of hours in two variables? Like
String startDay = 21/05/2020 00:00:00
String endDay = 21/05/2020 23:59:59
You can use java LocalDate like this:
final LocalDate now = LocalDate.now();
final LocalDate yesterday = now.minusDays(1);
final LocalDateTime start = yesterday.atStartOfDay();
final LocalDateTime end = yesterday.atTime(LocalTime.MAX);
And then format date to your desired format.
You can use a ZonedDateTime as an alternative to the answer given by #ArtyomRebrov.
It will take the system time zone implicitly if you don't provide a specific one.
See this example:
public static void main(String[] args) {
// get a datetime plus time zone information using the system time zone
ZonedDateTime startToday = ZonedDateTime.now()
// subtract a day
.minusDays(1)
// and take the minimum time a day can have
.with(LocalTime.MIN);
// use the same datetime to create the end of the day using the maximum time for a day
ZonedDateTime endToday = startToday.with(LocalTime.MAX);
// then print the results in date-time format and as epoch millis
System.out.println("Yesterday's beginning:\t" + startToday + "\t\t\t| "
+ startToday.toInstant().toEpochMilli());
System.out.println("Yesterday's end:\t" + endToday
+ "\t| " + endToday.toInstant().toEpochMilli());
}
Which outputs (on my maching in Germany):
Yesterday's beginning: 2020-05-21T00:00+02:00[Europe/Berlin] | 1590012000000
Yesterday's end: 2020-05-21T23:59:59.999999999+02:00[Europe/Berlin] | 1590098399999
I want to compare two dates.
If the current date time is greater or after the
specific date , then it will return 'True'.
So far I have tried this.
String deadline = "25/11/2017 11:00:00";
DateTime utc = new DateTime(DateTimeZone.UTC);
DateTimeZone timeZone = DateTimeZone.forID("Asia/Dhaka");
DateTime dhakaTime = utc.toDateTime(timeZone);
//Dead Line Time
DateTimeFormatter format = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
DateTime deadlineTime = format.parseDateTime(deadline.trim());
//Comapare
return deadlineTime.isAfter(dhakaTime.plusDays(2));
As today is 23 and dhakaTime.plusDays(2) will be 25 so it should return
"true".
But I am getting "false".
Output value :
dhakaTime.plusDays(2) = 2017-11-25T14:10:27.762+06:00
deadlineTime = 2017-11-25T11:00:00.000+06:00
Am i missing something or doing something wrong?
It gives false correctly.
You're comparing
deadLineTime = 2017-11-25T11:00:00.000+06:00 and
dhakaTime(+2) = 2017-11-25T14:10:27.762+06:00
They both are at same date, but with time, deadLineTime is at 11AM but dhakaTime(+2) is at 2PM. So,
(Nov 25, 2017 11AM)isAfter(Nov 25, 2017 2PM) is false.
EDIT: Testcases
As you mentioned you're testing, The following used different test cases for comparing deadLine with dhakaTime (+1, and +2 days). I hope this gives you an idea about how this works.
public static void main(String[] args) {
String deadline = "25/11/2017 11:00:00";
DateTime utc = new DateTime(DateTimeZone.UTC);
DateTimeZone timeZone = DateTimeZone.forID("Asia/Dhaka");
DateTime dhakaTime = utc.toDateTime(timeZone);
//Dead Line Time
DateTimeFormatter format = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
DateTime deadlineTime = format.parseDateTime(deadline.trim());
System.out.println("Deadline : " + deadline);
System.out.println("Current datetim : " + dhakaTime);
System.out.println("current datetime + 1 day : " + dhakaTime.plusDays(1));
System.out.println("current datetime + 2 day : " + dhakaTime.plusDays(2));
System.out.println("Is deadline after current datetime:" + deadlineTime.isAfter(dhakaTime));
System.out.println("Is deadline after current datetime + 1 day:" + deadlineTime.isAfter(dhakaTime.plusDays(1)));
System.out.println("Is deadline after current datetime + 2 day:" + deadlineTime.isAfter(dhakaTime.plusDays(2)));
}
Try using the method DateTimeFormatter withZone(DateTimeZone zone) and use that to create the DateTime
I want to get the time in UTC time zone. So I wrote the code:
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;
public class RegularSandbox {
public static void main(String[] args) {
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println("DATETIME = " + Date.from(utc.toInstant()));
}
}
The problem is the output shows me the time in PST (my local timezone). I need it to output the time in UTC so I can store it inside of my databases.
System.out.println("DATETIME = " + utc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
You do too much when trying to convert to old java.util.Date. And then you implicitly use its method toString() which should be well known for the observed behaviour to print the instant always in your system timezone.
But printing in UTC timezone is extremely simple, not even a formatter is needed if you can cope with ISO-8601-notation:
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println("DATETIME = " + utc.toInstant());
// output: DATETIME = 2015-12-30T15:01:18.483Z (Instant is always printed with UTC offset)
System.out.println("DATETIME = " + utc);
// output: DATETIME = 2015-12-30T15:01:57.611Z (the same because you
// have explicitly set the UTC Offset when constructing the ZonedDateTime)
You see, the behaviour of toString() of the new Java-8 classes Instant and ZonedDateTime is much clearer and is always in ISO-format. No need for a confusing conversion to Date.
About specialized formatters, you will only need one if you intend to deviate from ISO-8601-format - maybe using localized month names or extra printing of weekdays etc. Example in US-style:
System.out.println(
"DATETIME = "
+ utc.format(DateTimeFormatter.ofPattern("MM/dd/uuuu h:mm:ss a xxx")));
// output: DATETIME = 12/30/2015 3:14:50 PM +00:00
Note that the answer of #LowLevel uses a wrong pattern. If you leave out the symbol a (AM/PM-marker) then you should not choose the half-day-hour-symbol h but H (24-hour-format). And the timezone or offset symbol (here x) is crucial because otherwise the printed datetime will not be automatically recognized as being in UTC timezone.
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
final SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMM d, yyyy hh:mm:ss a z"); // you can specify format that you want to get
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC time: " + sdf.format(utc));
private Calendar getUTCTime(){
Calendar calendar = Calendar.getInstance();
// Assuming your time is in utc + 8
calendar.add(Calendar.HOUR, -8);
return calendar;
}
I suggest you to use Joda-Time.
DateTime dt = new DateTime(DateTimeZone.UTC);
I have a timestamp coming from an API in this format:
yyyy-MM-dd'T'HH:mm:ss.SSSSSS
I want to format it for the user in their own timezone (on android). This is what I'm doing:
String timestampFromApi = "...";
DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
Date date = df1.parse(timestampFromApi);
DateFormat df2 = new SimpleDateFormat();
Log.v(TAG, "In your timezone: " + df2.format(date));
But this prints the time in UTC. For example, if the timestamp happened at 4pm UTC time, and I am in PDT, the result is that it still prints "4pm".
I checked the timezone being used:
df2.getTimeZone()
and it does print out PDT for my device. What have I done wrong here?
Thanks
You're on the right track. You got the UTC time from the server, but now you just need to calculate the local offset when formatting. Try something like this:
private String formatTime(String timestampFromApi){
SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
df1.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = df1.parse(timestampFromApi);
Log.v(TAG, "In your timezone: " + df1.format(getAdjustedTime(date.getTime())));
}
private Date getAdjustedTime(long utcDate){
return new Date(utcDate + TimeZone.getDefault().getOffset(new Date().getTime()));
}
The getAdjustedTime() method will create a new Date object based on the UTC-offset from the local TimeZone.
The records are getting saved according to time zone of US but if I want to show the same record back to user it should convert the server date time with(US Time Zone) to user's date time with user's Time Zone
If you type in google "Java date change timezone" or "Javascript date change timezone". You will have one of your results:
In Java (source: http://www.coderanch.com/t/417443/java/java/Convert-Date-one-timezone-another )
Date date = new Date();
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("CET"));
// Prints the date in the CET timezone
System.out.println(formatter.format(date));
// Set the formatter to use a different timezone
formatter.setTimeZone(TimeZone.getTimeZone("IST"));
// Prints the date in the IST timezone
System.out.println(formatter.format(date));
Javascript (source: http://www.techrepublic.com/article/convert-the-local-time-to-another-time-zone-with-this-javascript/6016329 )
// function to calculate local time
// in a different city
// given the city's UTC offset
function calcTime(city, offset) {
// create Date object for current location
d = new Date();
// convert to msec
// add local time zone offset
// get UTC time in msec
utc = d.getTime() + (d.getTimezoneOffset() * 60000);
// create new Date object for different city
// using supplied offset
nd = new Date(utc + (3600000*offset));
// return time as a string
return "The local time in " + city + " is " + nd.toLocaleString();
}
// get Bombay time
alert(calcTime('Bombay', '+5.5'));
java.time
The old date-time classes are poorly designed, confusing, and troublesome. Avoid them.
Use modern classes: the java.time framework built into Java 8 and later. Find back-ports for earlier Java 6 & 7 and for Android.
An Instant is a moment on the timeline in UTC.
Instant now = Instant.now();
Apply a time zone (ZoneId) to get a ZonedDateTime.
Never use the 3-4 letter zone abbreviations such as EST or IST. They are neither standardized nor unique(!). Use proper time zone names, built in a continent/region format such as Asia/Kolkata, Pacific/Auckland, America/Los_Angeles.
ZoneId zoneId_Montreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt_Montreal = ZonedDateTime.ofInstant( instant , zoneId_Montreal );
Apply a different time zone to generate another ZonedDateTime adjusted to that time zone. Call withZoneSameInstant.
ZoneId zoneId_Paris = ZoneId.of( "Europe/Paris" ); // Or "Asia/Kolkata", etc.
ZonedDateTime zdt_Paris = zdt_Montreal.withZoneSameInstant( zoneId_Paris );
If you want to go back to UTC, ask for an Instant.
Instant instant = zdt_Paris.toInstant();
TimeZone fromTimezone =TimeZone.getTimeZone(from);
TimeZone toTimezone=TimeZone.getTimeZone(to);
long fromOffset = fromTimezone.getOffset(calendar.getTimeInMillis());
long toOffset = toTimezone.getOffset(calendar.getTimeInMillis());
long convertedTime = calendar.getTimeInMillis() - (fromOffset - toOffset);
//Convert date from one zone to another
/*
$zone_from='Asia/Kolkata';
$zone_to='America/Phoenix';
date_default_timezone_set($zone_from);
$convert_date="2016-02-26 10:35:00";
echo $finalDate=zone_conversion_date($convert_date, $zone_from, $zone_to);
*/
function zone_conversion_date($time, $cur_zone, $req_zone)
{
date_default_timezone_set("GMT");
$gmt = date("Y-m-d H:i:s");
date_default_timezone_set($cur_zone);
$local = date("Y-m-d H:i:s");
date_default_timezone_set($req_zone);
$required = date("Y-m-d H:i:s");
/* return $required; */
$diff1 = (strtotime($gmt) - strtotime($local));
$diff2 = (strtotime($required) - strtotime($gmt));
$date = new DateTime($time);
$date->modify("+$diff1 seconds");
$date->modify("+$diff2 seconds");
return $timestamp = $date->format("Y-m-d H:i:s");
}
Code To Get Berlin Time and Convert it into UTC Time
Calendar sc = Calendar.getInstance(TimeZone.getTimeZone("Europe/Berlin"));
String strt = null;
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
sf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
sc.set(sc.get(Calendar.YEAR),sc.get(Calendar.MONTH), sc.get(Calendar.DATE),sc.get(Calendar.HOUR) , sc.get(Calendar.MINUTE));
strt = sf.format(sc.getTime());
System.out.println("Start :"+strt);