I have a date string of format MM/dd/yyyy that I am parsing using SimpleDateFormat
Now say the startDateString is 11/26/2012 for the code given below. I set the time zone to America/New_York
SimpleDateFormat df=new SimpleDateFormat("MM/dd/yyyy");
Date st = df.parse(startDateString);
Calendar startDate = Calendar.getInstance(TimeZone.getTimeZone("America/New_York"));
System.out.println("BEFORE : Start Date :"+startDate.getTime());
startDate.setTime(st);
System.out.println("AFTER : Start Date :"+startDate.getTime());
DateTimeZone timezone = DateTimeZone.forID("America/New_York");
DateTime actualStartDate = new DateTime(startDate,timezone);
System.out.println("JODA DATE TIME "+ actualStartDate);
The outout of above code snippet:
BEFORE : Start Date :Tue Nov 27 12:26:51 IST 2012
AFTER : Start Date :Mon Nov 26 00:00:00 IST 2012 //ok it sets date to 26th
//with all time parameters as 0.
JODA DATE TIME 2012-11-25T13:30:00.000-05:00 // here the date and
// time parameter are changed
What my problem is when I create my actualStartDate like this :
DateTime actualStartDate = new DateTime(startDate,timezone);
The date changes to 25 and the time changes to 13:00:00
I think this is because of timezone zone difference between India and US (total -10:30 from IST Indian time)
What I want is JODA DATE TIME 2012-11-26T00:00:00.000-05:00
Do I manually set the parameters of time inside my startDate calendar instance to 0 ?
I suspect the problem is that you're parsing in your default time zone. This:
AFTER : Start Date :Mon Nov 26 00:00:00 IST 2012
shows that the instant in time you're using is midnight IST - not midnight in New York or in UTC. Currently IST is 18:30 in UTC, so the instant you're representing is 25-11-25T18:30:00Z.
When you convert that into New York time, you end up with 2012-11-25T13:30:00-05:00, which is exactly what Joda Time is doing.
I would strongly advise that:
You avoid using the Java libraries at all (that's where all the problems have come from here - both in parsing, and the result of Date.toString() confusing you)
You use LocalDate to represent a date, rather than DateTime. You're trying to represent a date after all, not an instant in time. This bypasses time zones entirely, as a date doesn't have a time zone.
Sample code:
import java.util.*;
import org.joda.time.*;
import org.joda.time.format.*;
public class Test {
public static void main (String[] args) {
String text = "11/26/2012";
DateTimeFormatter formatter =
DateTimeFormat.forPattern("MM/dd/yyyy")
.withLocale(Locale.US);
LocalDate date = formatter.parseLocalDate(text);
System.out.println(date);
}
}
Once you've got a LocalDate, if you want to find out the instant at which that day started in a particular time zone, you can use LocalDate.toDateTimeAtStartOfDay(DateTimeZone).
Related
I have a DateTime in the format of Tue, 30 Apr 2019 16:00:00 +0800 which is RFC 2822 formatted date
I need to convert this to the given timezone in the DateTime which is +0800
So if i summarized,
DateGiven = Tue, 30 Apr 2019 16:00:00 +0800
DateWanted = 01-05-2019 00:00:00
How can i achieve this in Java?
I have tried the below code but it gives 08 hours lesser than the current time which is
30-04-2019 08:00:00
Code i tried
String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern);
Date startDate = format.parse(programmeDetails.get("startdate").toString());
//Local time zone
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
//Time in GMT
Date dttt= dateFormatLocal.parse( dateFormatGmt.format(startDate) );
You are on right approach but just use java-8 date time API module, first create DateTimeFormatter with the input format representation
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss Z");
And then use OffsetDateTime to parse string with offset
OffsetDateTime dateTime = OffsetDateTime.parse("Tue, 30 Apr 2019 16:00:00 +0800",formatter);
And the call the toLocalDateTime() method to get the local time
LocalDateTime localDateTime = dateTime.toLocalDateTime(); //2019-04-30T16:00
If you want the output in particular format again you can use DateTimeFormatter
localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) //2019-04-30T16:00:00
Note : As #Ole V.V pointed in comment, after parsing the input string into util.Date you are getting the UTC time
The class Date represents a specific instant in time, with millisecond precision.
So now if you convert the parsed date time into UTC you get 2019-04-30T08:00Z without offset, so you can use withOffsetSameInstant to convert it into any particular timezone
dateTime.withOffsetSameInstant(ZoneOffset.UTC)
You misunderstood. According to RFC 2822 +0800 means that an offset of 8 hours 0 minutes has already been applied to the time compared to UTC. So the output you got was the correct GMT time.
java.time
I recommend you skip the old and outdated classes SimpleDateFOrmat and Date. It’s much nicer to work with java.time, the modern Java date and time API. Furthermore it has the RFC format built in, so we don’t need to write our own formatter.
OffsetDateTime parsedDateTime = OffsetDateTime
.parse("Tue, 30 Apr 2019 16:00:00 +0800",
DateTimeFormatter.RFC_1123_DATE_TIME);
ZonedDateTime dateTimeInSingapore
= parsedDateTime.atZoneSameInstant(ZoneId.of("Asia/Singapore"));
System.out.println("In Singapore: " + dateTimeInSingapore);
OffsetDateTime dateTimeInGmt
= parsedDateTime.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("In GMT: " + dateTimeInGmt);
Output:
In Singapore: 2019-04-30T16:00+08:00[Asia/Singapore]
In GMT: 2019-04-30T08:00Z
The built-in formatter is named RFC_1123_DATE_TIME because the same format is used in multiple Requests for Comments (RFCs).
Links
RFC 2822 Internet Message Format
Oracle tutorial: Date Time explaining how to use java.time.
with the help of #ole v.v's explanation i have separated the datetime value for two
1. time
2. timezone
then i used this coding to extract the datetime which is related to the given timezone
//convert datetime to give timezone
private static String DateTimeConverter (String timeVal, String timeZone)
{
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat offsetDateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
offsetDateFormat2.setTimeZone(TimeZone.getTimeZone(timeZone));
String result =null;
try {
result = offsetDateFormat2.format(format.parse(timeVal));
} catch (java.text.ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
I am trying to convert UTC Date to IST. But to my surprise, after converting everything, it is still returning me UTC only. How is it possible?
INPUT:
StartDateTimeUtc='2017-09-15T14:00:00',
EndDateTimeUtc='2017-09-15T15:00:00'
Code:
public static final String DATE_FORMATE_CURRENT = "yyyy-MM-dd'T'HH:mm:ss";
Date meetingStartDate = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(model.StartDateTimeUtc);
Date meetingEndDate = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(model.EndDateTimeUtc);
//Convert Date to String
DateFormat df = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT);
String meetinStartDateString = df.format(meetingStartDate);
String meetingEndDateString = df.format(meetingEndDate);
//Convert String Date to IST
SimpleDateFormat dftwo = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT);
dftwo.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
Date date = null;
Date datetwo = null;
try {
date = dftwo.parse(meetinStartDateString);
datetwo = dftwo.parse(meetingEndDateString);
} catch (ParseException e) {
e.printStackTrace();
}
dftwo.setTimeZone(TimeZone.getDefault());
String formattedStartDate = dftwo.format(date);
String formattedEndDate = dftwo.format(datetwo);
//Convert String Date back to Date format so that we can pass into Calendar code
Date meetingStartDateFinal = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(formattedStartDate);
Date meetingEndDateFinal = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(formattedEndDate);
OUTPUT again in UTC:
Start Date : Fri Sep 15 14:00:00 GMT+05:30 2017
End Date : Fri Sep 15 15:00:00 GMT+05:30 2017
A java.util.Date doesn't have any timezone information. It just contains one value: the number of milliseconds since unix epoch (1970-01-01T00:00Z, or January 1st 1907, at midnight in UTC).
This number of milliseconds is the same, everywhere in the world. What's is different is the corresponding date and time in each timezone. Example: right now, this millis value is 1505481835424, which corresponds, in UTC, to 2017-09-15T13:23:55.424Z. This same value corresponds to 10:23 AM in São Paulo, 18:53 in Kolkata, 14:23 in London and so on. The local date/time is different in each timezone, but the millis value is the same for everyone.
That's why you don't convert a Date itself: the millis value is the same, and there's no need to change it. What you can change is the representation of this date in different timezones.
SimpleDateFormat, by default, uses the JVM default timezone to parse dates. But if you know that the inputs are in a specific zone, you must set in the formatter. So, to parse your inputs, you must do:
String startDateTimeUtc = "2017-09-15T14:00:00";
String endDateTimeUtc = "2017-09-15T15:00:00";
SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss");
// input is in UTC
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
// parse dates
Date meetingStartDate = sdf.parse(startDateTimeUtc);
Date meetingEndDate = sdf.parse(endDateTimeUtc);
The 2 Date objects above will correspond to 14:00 and 15:00 UTC (which is the same as 19:30 and 20:30 in Kolkata timezone).
But if you just print the Date objects directly (using System.out.println, logging, or even checking their values in a debugger), it'll implicity call the toString() method, which uses the JVM default timezone behind the scenes, resulting in the output you're seeing (Fri Sep 15 14:00:00 GMT+05:30 2017).
If you want to print in a specific format, and in a specific timezone, you'll need another formatter:
// another formatter for output
SimpleDateFormat outputFormat= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
// output will be in Asia/Kolkata timezone
outputFormat.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
System.out.println(outputFormat.format(meetingStartDate));
System.out.println(outputFormat.format(meetingEndDate));
The output will be:
2017-09-15T19:30:00
2017-09-15T20:30:00
Which corresponds to the same UTC dates in Kolkata timezone.
Just remember: you don't convert the Date's between timezones (because their millis values are "absolute" - they are the same for everyone in the world). You just change the String representation of those dates (the corresponding date/time in a specific timezone).
Java new Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
In Android you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need the ThreeTenABP (more on how to use it here).
This new API has lots of different date/time types for each situation. In this case, the inputs have date and time, but no timezone information, so first I parse them to a org.threeten.bp.LocalDateTime, using a org.threeten.bp.format.DateTimeFormatter:
// parse the inputs
DateTimeFormatter fmt = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
LocalDateTime startDt = LocalDateTime.parse(startDateTimeUtc, fmt);
LocalDateTime endDt = LocalDateTime.parse(endDateTimeUtc, fmt);
Then I use a org.threeten.bp.ZoneOffset to convert them to UTC, and later a org.threeten.bp.ZoneId to convert this to another timezone. The result will be a org.threeten.bp.ZonedDateTime:
// input is in UTC
ZoneOffset utc = ZoneOffset.UTC;
// convert to Asia/Kolkata
ZoneId zone = ZoneId.of("Asia/Kolkata");
ZonedDateTime start = startDt.atOffset(utc).atZoneSameInstant(zone);
ZonedDateTime end = endDt.atOffset(utc).atZoneSameInstant(zone);
Then I use the same DateTimeFormatter to format the output:
System.out.println(fmt.format(start));
System.out.println(fmt.format(end));
The output is:
2017-09-15T19:30:00
2017-09-15T20:30:00
Note that I don't need to set the timezone in the formatter, because the timezone information is in the objects (they are responsible to do the conversion).
I've timestamp based on IST ( Indian Standard Time / GMT + 5:30 Hrs), My application shows last activity time based on device timestamp.
that is current time - activity timestamp. Its fine when the device timezone is IST.
For example,
Activity timestamp - 11/Feb/2016 09:00:00 AM
Current timestamp (IST) - 11/Feb/2016 10:00:00 AM
My Calculation = Current timestamp - Activity timestamp
So Application shows 1 hr ago
But the device timezone changed to some other like PHT for the same time (Philippine Time / GMT + 8 Hr)
Activity timestamp - 11/Feb/2016 09:00:00 AM
Current timestamp(PHT) - 11/Feb/2016 12:30:00 AM (plus 2:30Hrs compare with IST)
My Calculation = Current timestamp - Activity timestamp
So Application shows 3 hrs 30 mis ago
My problem is, How to get the IST time always using java? whatever the timezone, I need IST time.
I tried below code, When i change the value to IST but the timezone automatically changed to device timezone.
Please refer below URL for source code http://goo.gl/dnvQF5
SimpleDateFormat sd = new SimpleDateFormat(
"yyyy.MM.dd G 'at' HH:mm:ss z");
Date date = new Date();
// TODO: Avoid using the abbreviations when fetching time zones.
// Use the full Olson zone ID instead.
sd.setTimeZone(TimeZone.getTimeZone("GMT"));
String gmtDate = sd.format(date);
System.out.println("GMT --> " + gmtDate);
String istDate = gmtDate.replace("GMT", "IST");
System.out.println("After Replace -> " + istDate);
sd.setTimeZone(TimeZone.getTimeZone("IST"));
try {
Date istConvertedDate = sd.parse(gmtDate);
System.out.println("After Convert --> " + istConvertedDate);
} catch (ParseException ex) {
ex.printStackTrace();
}
I got output like
GMT --> 2016.02.11 AD at 05:20:07 GMT
After Replace -> 2016.02.11 AD at 05:20:07 IST
After Convert --> Thu Feb 11 00:20:07 EST 2016
Please help me to resolve this.
The class java.util.Date is only a thin wrapper around elapsed milliseconds since UNIX epoch (1970-01-01T00:00:00Z). Objects of this type don't carry any format or timezone information. Therefore every such object has completely lost the timezone information after parsing a text with timezone identifier or name using SimpleDateFormat.
What you observe and are confused about is the fact that the method toString() of this class uses a specific representation based on the system timezone.
Another thing: If you apply a string manipulation replacing "GMT" by "IST" (an ambivalent timezone name - Israel? India? Ireland?) then you effectively change the moment/instant while keeping the local time representation. Do you really want this?
If you want to preserve the timezone information which was originally parsed then you could use ZonedDateTime in the library Threeten-ABP or DateTime in the library Joda-Time-Android or ZonalDateTime in my library Time4A.
Try
public static void main(String[] args) {
SimpleDateFormat sd = new SimpleDateFormat(
"yyyy.MM.dd G 'at' HH:mm:ss z");
Date date = new Date();
// TODO: Avoid using the abbreviations when fetching time zones.
// Use the full Olson zone ID instead.
sd.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sd.format(date));
String gmtDate = sd.format(date);
System.out.println(gmtDate);
//Here you create a new date object
Date istDate= new Date();
sd.setTimeZone(TimeZone.getTimeZone("IST"));
String istDate=sd.format(istDate);
System.out.println(istDate)
}
This way the first printed time will be GMT and second will be ISD.
You can use java.util.Calendar
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("IST"));
this calendar contains current time in IST timeZone.
You can set timeStamp:
calendar.setTimeInMillis(timeStamp);
And get java.util.Date or time stamp
Date date = calendar.getTime();
Long timeStamp = calendar.getTimeInMillis();
Replace
sd.setTimeZone(TimeZone.getTimeZone("IST"));
to
TimeZone.setDefault(TimeZone.getTimeZone("IST"));
How do I get Current Time as this code is giving (Time-->Thu Jan 01 05:56:27 ACT 1970)??
DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss.SS");
Date time = new Date();
String currentTime=timeFormat.format(time);
time=timeFormat.parse(currentTime);
System.out.println("Time-->"+time);
salesOrder.setOrderTime(time);
Class java.util.Date is not suitable for storing only a time-of-day (hours, minutes, seconds, milliseconds). Class Date is a timestamp, it contains a number of milliseconds since 01-01-1970, 00:00:00 GMT.
Use LocalTime from the Joda Time library for this instead.
Note: What you are doing in your code is first formatting a Date object to a String, and then parsing it back to a Date again, throwing away the day, month, year part. What you end up with is a Date object that's set to a number of hours, minutes, seconds and milliseconds since 01-01-1970, 00:00:00 GMT.
use DateFormat timeFormat = new SimpleDateFormat();
instead of
DateFormat timeFormat = new SimpleDateFormat("HH:MM:ss:SS");
The problem is in formatting. You have not provided the Day,year fieldr, thats why it is acting that way. Or You can use this with proper formatting :
DateFormat timeFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
EDIT:
Try this:
Calendar c = Calendar.getInstance();
c.setTime(time);
System.out.println(c.get(Calendar.YEAR)+ " "+c.get(Calendar.MONTH)+ " "+ c.get(Calendar.DAY_OF_MONTH));
Where time set in Calendar object is time that is not parsed/formatted using simpleDateFormat.
From calendar object, you can get individual month , day , year and use it the way you like, or you can just call c.getTime() to get the Date object.
Your format only contains hours and minutes and seconds. Given just a time of day with no date component, DateFormat.parse() does not fill in the current date; it falls back on the epoch of the system, "time zero", which is January 1, 1970. If you want a date string that can be turned back into a Date object, you need to include the year and month and day as well as the hour.
I have written two functions - today() and todayUTC() - as:
public static Date today() {
Calendar cal = Calendar.getInstance();
return cal.getTime();
}
public static Date todayUTC() {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
return cal.getTime();
}
But when I print the results of these functions using:
public void todayTest() {
Date date1 = OOTBFunctions.today();
System.out.println("today: "+date1);
Date dateUTC1 = OOTBFunctions.todayUTC();
System.out.println("todayUTC: "+dateUTC1);
}
I saw that both statements print the same value i.e.
today: Thu Aug 30 14:48:56 PDT 2012
todayUTC: Thu Aug 30 14:48:56 PDT 2012
Can anybody suggest what am I missing in UTC function that I am getting local timezone date.
Java uses the default Locale while printing and that is why you see that behavior. Use code like below to format and print it in the locale/format you want. Remember
When you create a Date object, it is always in UTC.
Display the date in the Locale of the user.
Store the date in UTC.
Code
final SimpleDateFormat sdf = new SimpleDateFormat("the format you want");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
final String utcTime = sdf.format(new Date());
You doesn't need both today() and todayUTC() methods. keep and like below
public static Date nowInUTC()
{
return new Date();
}
You doesn't need to test anything.
Both of your methods will return the same value - a Date object doesn't have any notion of a time zone (unlike a Calendar). A Date just represents an instant in time, stored internally as the number of milliseconds since midnight January 1st 1970, UTC. Effectively, you've got two methods which are equivalent to:
return new Date(System.currentTimeMillis());
Date.toString() always uses the system default time zone.
If you want to maintain a date/time with a time zone, consider just using Calendar. If you want to format a particular instant in time in a time zone, just use SimpleDateFormat having set the time zone.
Ideally, change to use Joda Time instead of Date or Calendar though - it's a much cleaner API.