when parsing using SimpleDateFormat the milliseconds of date object is not correct
Date locally=new SimpleDateFormat("H:mm").parse("03:00");
the locally milliseconds is 3600000 but the true result must be 3*60*60*1000=10800000
Parsing a timezone-less information like "03:00" to a global type like Date is always timezone-relevant. In your case parsing uses the default timezone of your system which has obviously an extra offset of two hours so you get the local time reduced by two hours, resulting in an UTC-timestamp of 1970-01-01T01:00Z.
It seems you want to interprete the input as kind of duration. Although a Date-object is naturally NOT a duration you might slightly misuse the Date-type this way:
SimpleDateFormat sdf = new SimpleDateFormat("H:mm");
sdf.setTimeZone(TimeZone.getTimeZone("GMT")); // interprete input in UTC (zero offset)
Date d = sdf.parse("03:00"); // timestamp equivalent to 1970-01-01T03:00Z
long durationInMillis = d.getTime(); // 10800000 ms relative to UNIX epoch
Related
In timestamp variable, I want to get the timestampt value with the current hour, minute and second. The currentDataTime gives me the time in this format: 2020-08-28 17:18:02.
Currently, the timestamp variable returns me 1598645882634 (the last 3 numbers are the miliseconds) but when I convert it in a online conversor to a Human readable format, it gives me 08/28/2020 # 8:18pm (UTC). The only one problem is the hour and minute tha is 3 hours different because of my zone. How can I convert the date AND time to timestamp?
object DateTime {
val currentDataTime: String
#SuppressLint("SimpleDateFormat")
get() {
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
return dateFormat.format(Date())
}
val timestamp: String
get(){
val formatter: DateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val date = formatter.parse(currentDataTime) as Date
return date.time.toString().dropLast(3) //it is returning
}
}
A Unix timestamp is defined to be (almost) UTC. It carries no timezone information so it cannot be shifted according to a timezone difference without everything based on it falling apart. (If you'd like to hardwire it anyway, according to your example just add your timezone difference in milliseconds. But read on first.)
Localized time can only be interpreted consistently as long as the proper timezone is attached. It jumps back and forth whenever daylight-savings time starts or ends. If that's not complicated enough, the rules for daylight-savings time may change at any time (and do so around the globe).
Your online converter apparently just took a UTC-based timestamp and displayed it according to your local timezone.
To handle localized date and time values, use the multiplatform date/time library kotlinx-datetime. In the README section Converting an instant to local date and time components you'll find this example:
val currentMoment: Instant = Clock.System.now()
val datetimeInUtc: LocalDateTime = currentMoment.toLocalDateTime(TimeZone.UTC)
val datetimeInSystemZone: LocalDateTime = currentMoment.toLocalDateTime(TimeZone.currentSystemDefault())
There you'll also find elaborate explanations on which type of date and time to use in which scenario.
I am getting the 4 hours difference on time zone from below lines of code on my device:
I am getting the time in such a way like 2018-09-30T13:45:00Z
My start and End Date is as follow: -
"start_date":"2017-09-13T12:15:00Z",
"end_date":"2018-09-30T13:45:00Z",
Calendar c = Calendar.getInstance(Locale.getDefault());
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date localStartDate = formatter.parse(startTime);
Date localEndDate = formatter.parse(endTime);
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm");
dateFormatter.setTimeZone(c.getTimeZone());
localStartDate = dateFormatter.parse(startTime);
localEndDate = dateFormatter.parse(endTime);
SimpleDateFormat monthFormat = new SimpleDateFormat("MMM");
monthFormat.setTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getDisplayName()));
String monthName = monthFormat.format(localStartDate);
eventDate.setMonth(monthName);
SimpleDateFormat dateFormat = new SimpleDateFormat("dd");
dateFormat.setTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getDisplayName()));
String dateName = dateFormat.format(localStartDate);
eventDate.setDate(dateName);
SimpleDateFormat dayNameFormat = new SimpleDateFormat("EEEE");
dayNameFormat.setTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getDisplayName()));
String dayName1 = dayNameFormat.format(localStartDate);
String dayName2 = dayNameFormat.format(localEndDate);
eventDate.setDayName1(dayName1);
eventDate.setDayName2(dayName2);
SimpleDateFormat timeFormat = new SimpleDateFormat("hh:mm a");
timeFormat.setTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getDisplayName()));
String startTimeName = timeFormat.format(localStartDate);
String endTimeName = timeFormat.format(localEndDate);
System.out.println("My Start date and end date==>>>"+startTimeName+" " +endTimeName );
Problem: Getting the 4 hours difference from above code, as I am setting my time zone to BOSTON(US), getting error.
My result from the below #Hugo solution is as below
And i am expecting the result as below
Please check it once..I have also set the TimeZone of Eastern DayLight Time but not getting proper solution..please check it once..And let me know
SimpleDateFormat and Calendar uses the JVM default timezone (unless you set a different one on them), and the default timezone can be different in each device/machine/environment. Not only that, this default can be changed without notice, even at runtime, so it's better to always make it explicit which one you're using.
When you do things like:
Calendar c = Calendar.getInstance(Locale.getDefault());
dateFormatter.setTimeZone(c.getTimeZone());
monthFormat.setTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getDisplayName()));
The Calendar is created with the default timezone, so dateFormatter will also have the same zone. So does monthFormat, and also the other formatters you created. The only formatter set to a different zone is the first one (which is set to UTC).
Also, the second formatter is redundant (it does the same thing that the first one is already doing: parsing the String to a Date), so you can remove it.
Assuming that your input is a String with the value 2018-09-30T13:45:00Z: the Z in the end indicates that this date is in UTC. So you should parse it using a formatter set to UTC. So, instead of using c.getTimeZone() and TimeZone.getDefault(), you should use only TimeZone.getTimeZone("UTC").
For the output, you must set the formatters with the timezone you want to convert to. If the timezone is "EDT", set to it (but don't use exactly "EDT", see below). If you want to use the JVM default, use TimeZone.getDefault() - just check this value before, to make sure the default is what you need.
Just keep in mind that short names like "EDT" and "EST" are not real timezones. Those abbreviations are ambiguous and not standard. Prefer to use IANA timezones names (always in the format Region/City, like America/New_York or Europe/Berlin).
So, when you do TimeZone.getTimeZone("EDT"), it usually returns "GMT" (because "EDT" is not recognized, and "GMT" is returned as default). That's because "EDT" is used by more than one timezone, so you must choose specifically which one you're using (I'm using America/New_York in these examples).
Another detail is that in the first 2 formatters you use hh, which means "hour of am/pm" (values from 1 to 12), but the input doesn't have AM/PM designators to properly resolve this. You need to change it to HH ("hour of day", with values from 0 to 23).
// input is in UTC
TimeZone inputZone = TimeZone.getTimeZone("UTC");
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
formatter.setTimeZone(inputZone);
Date localStartDate = formatter.parse(startTime);
Date localEndDate = formatter.parse(endTime);
...
// removed the second formatter (it was redundant)
// output is in EST (America/New_York)
// or use TimeZone.getDefault() to get JVM default timezone
TimeZone outputZone = TimeZone.getTimeZone("America/New_York");
SimpleDateFormat monthFormat = new SimpleDateFormat("MMM");
monthFormat.setTimeZone(outputZone);
...
SimpleDateFormat dateFormat = new SimpleDateFormat("dd");
dateFormat.setTimeZone(outputZone);
...
SimpleDateFormat dayNameFormat = new SimpleDateFormat("EEEE");
dayNameFormat.setTimeZone(outputZone);
...
SimpleDateFormat timeFormat = new SimpleDateFormat("hh:mm a");
timeFormat.setTimeZone(outputZone);
...
System.out.println("My Start date and end date==>>>" + startTimeName + " " + endTimeName);
With this, you're explicity using UTC for input and a specific timezone for output, instead of relying on the JVM default timezone (which can be different in each device and you can't control).
The output is:
My Start date and end date==>>>08:15 AM 09:45 AM
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).
First you can use a org.threeten.bp.Instant to parse the input, because it's in UTC (designated by the Z in the end). Then you use a org.threeten.bp.ZoneId to convert it to a org.threeten.bp.ZonedDateTime:
// output timezone
// or use ZoneId.systemDefault() to get JVM default timezone
ZoneId zone = ZoneId.of("America/New_York");
// parse the inputs
ZonedDateTime startDate = Instant.parse(startTime).atZone(zone);
ZonedDateTime endDate = Instant.parse(endTime).atZone(zone);
Then you can use these objects to get the other fields:
// get month name
System.out.println(startDate.getMonth().getDisplayName(TextStyle.SHORT, Locale.getDefault()));
This is equivalent to MMM pattern, and it will print the month name in the default locale. If you want the month name in a specific language, just use another java.util.Locale value (such as Locale.ENGLISH or any other one as described in the javadoc).
The org.threeten.bp.format.TextStyle defines if the month name will be narrow (usually just one letter), short (usually 2 or 3 letters) or full (the full name). The output varies according to the locale used.
I personally prefer to not use the default locale, because it can be changed without notice, even at runtime. It's always better to specify the locale you want.
To get the day of month, you can choose to get it as an int or as a formatted String (using a org.threeten.bp.format.DateTimeFormatter):
// get day of month as int
int day = startDate.getDayOfMonth(); // 30
// get day of month as formatted string
String dayStr = DateTimeFormatter.ofPattern("dd").format(startDate); // 30
To get the day of week, it's similar to the code used to get the month:
// get day of week
System.out.println(startDate.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault()));
The same logic applies here: the TextStyle defines how the name will be (in this case, FULL is equivalen to EEEE, and it prints the full name), and the locale defines the language used.
Finally, to get the corresponding time, you can use another DateTimeFormatter:
// get time
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("hh:mm a");
System.out.println(fmt.format(startDate)); // 08:15 AM
System.out.println(fmt.format(endDate)); // 09:45 AM
This will the date/time in the timezone you chose for the output.
If you're going to use the JVM default (ZoneId.systemDefault()), just check its value before to make sure it's the one you want (it might not be because this can be changed at runtime, so it's always better to specify one).
I currently work on a double value that represent the total consumed time
for example, I have a 260 that means 260 second is consumed
To display to user, I would like to format it
for example , it should be something like 0year,0month,0day,1hr,2min,30sec
But I found the SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); is not quite suit my case (seems the "h" in "hr" is conflicted with the hour symbol?)
So , how to change the HH:mm:ss to the case mentioned above?
Thanks for helping
DateFormat is useful to format dates, not an absolute value of time.
To achieve your goal, you can take a look to Formatter
Hope this sample helps you:
String total_consumed_time = String.format("%01d year, %01d month, %01d day, %01d hr, %01d min, %01d sec", time_year, time_month, time_day, time_hour, time_min, time_seg);
I didn't try that code, but I use similar workaround with an absolute time in milliseconds:
long time = 260000; // time in mseg
long time_hour = TimeUnit.MILLISECONDS.toHours(time);
time -= TimeUnit.HOURS.toMillis(time_hour);
long time_min = TimeUnit.MILLISECONDS.toMinutes(time);
time -= TimeUnit.MINUTES.toMillis(time_min);
long time_seg = TimeUnit.MILLISECONDS.toSeconds(time);
String total_time = String.format("%02d:%02d:%02d", time_hour, time_min, time_seg);
With a result of "00:04:20" (4 minutes and 20 seconds).
Accepted answer is in most cases okay for solving your problem, but gives wrong reason why not to use the class SimpleDateFormat. This format class is well suited for objects of type java.util.Date (which are kind of unix timestamps in milliseconds hence absolute value of time, NOT dates). In order to treat letters like "hr" as literals you need to escape them. Example code:
// create timestamp
java.util.Date jud = new java.util.Date(260 * 1000); // milliseconds
// create format for timestamp
SimpleDateFormat sdf =
new SimpleDateFormat("yyyy'year',M'month',d'day',H'hr',m'min',s'sec'");
// otherwise you will get extra offset time (example: in England +1 hour DST)
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
// output: 1970year,1month,1day,0hr,4min,20sec
String formatted = sdf.format(jud);
System.out.println(formatted);
Even with the applied and tricky time zone correction in code you face the problem that you have an output for the year 1970, a point in time. Hereby you can see that SimpleDateFormat does format timestamps well (absolute values in time) but NOT durations (amount resp. length of time). This semantic problem can also not be solved by the approach to use java.util.Formatter as soon as the input increases the day limit of 86400 seconds.
Old JDK and Android don't offer a built-in solution for evaluating time differences expressed in years, months and days. Java 8 does offer (limited) support with new API (class 'Period' only for date part, not time part). External libraries like JodaTime or my own one (actually only as alpha-version) give more support. JodaTime even offers a special PeriodFormatter which is ideal for solving your problem.
I am having following code to convert milliseconds to Android Date object.
Date dateObj = new Date(milli);
But problem is that my milliseconds value is having GMT value added in it before i pass it to Date class, add when i print this date object i can see that date object is again adding GMT value in the milliseconds value and because of that my date is displayed as wrong.
So how can i generate Date object with out considering GMT value in it.
For example my milliseconds are 1385569800000 which is getting printed as below:
Wed, 27 Nov 2013 22:00:00 --> +5.30
But the current value of this time stamp without adding GMT is:
Wed, 27 Nov 2013 16:30:00
*UPDAE*
It is not just about printing the date in right format and with right date time.
But i want to use that date object to schedule TimeTask.
So basically i want to create Date object which has proper date time value in it with out adding extra GMT time added in it.
A Date is always in UTC. No need to change that.
When printing the date value, use SimpleDateFormat and call setTimeZone() on it before formatting the output string.
It is not just about printing the date in right format and with right date time.
But i want to use that date object to schedule TimeTask.
TimerTask is just a task and not its scheduling. Timer accepts a Date object for scheduling. The Date is in UTC there as well.
try my code if you a
long currentTime = System.currentTimeMillis();
TimeZone tz = TimeZone.getDefault();
Calendar cal = GregorianCalendar.getInstance(tz);
int offsetInMillis = tz.getOffset(cal.getTimeInMillis());
currentTime -= offsetInMillis;
Date date = new Date(currentTime);
it is work for me
You can try with joda-time API.
Joda-Time provides a quality replacement for the Java date and time classes. The design allows for multiple calendar systems, while still providing a simple API. The 'default' calendar is the ISO8601 standard which is used by XML. The Gregorian, Julian, Buddhist, Coptic, Ethiopic and Islamic systems are also included, and we welcome further additions. Supporting classes include time zone, duration, format and parsing.
http://joda-time.sourceforge.net/key_instant.html
A Date object simply represents a moment in time. Imagine you're on the phone to someone on a different continent, and you say "3...2...1...NOW!". That "NOW" is the same moment for both of you, even though for one person it's 9am and for the other it's 4pm.
You're creating a Date representing the moment 1385569800000 milliseconds after the Java epoch (the beginning of 1970, GMT). That is your "NOW", and it's fixed and unchanging. What it looks like converted into text, however, depends on which timezone you want to display it for. Java defaults to using GMT, which would be right if you were in Britain during the winter, but for (I'm guessing) India you want it in a different time zone. Laalto's answer shows you how to do that.
here is the code,that worked like charm for me:
public static String getDate(long milliSeconds, String dateFormat)
{
// Create a DateFormatter object for displaying date in specified format.
DateFormat formatter = new SimpleDateFormat(dateFormat);
// Create a calendar object that will convert the date and time value in milliseconds to date.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(milliSeconds);
return formatter.format(calendar.getTime());
}
I'm trying to convert event timestamp in a date, my code:
Calendar c = Calendar.getInstance();
c.setTimeInMillis(event.timestamp/1000000);//time in ms (timestamp is in ns)
System.out.println((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(c.getTime()));
How come I get 1970-01-02?
I assume that you are using SensorEvent.timestamp. The documentation fails to mention that this is the awake time in nanoseconds since the last boot (comparable to SystemClock.uptimeMillis()), not time since Unix epoch. In short, it appears your device has been awake for less than two days.
Also, Calendar.getTime() returns a Date object and there is a Date constructor that takes milliseconds so you can shorten your code:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date(event.timestamp / 1000000)));