It was discussed too many times, I know, but I can't get why the milliseconds generated by mine:
System.currentTimeMillis();
Or by:
Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTimeInMillis()
Are not equal to what I see on www.epochconverter.com?
What I need is to merely generate a String of concrete format, but I've found out the milliseconds aren't right.
Just in case here is how I do it:
private static final String DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
public static String getCurrentTimestamp() {
long time = System.currentTimeMillis();
SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);
String lastModifiedTime = sdf.format(time);
Logger.logVerbose(TAG, "Generated timestamp is " + lastModifiedTime);
return lastModifiedTime;
}
What I finally get is just a local time, but I need the only time which is pure UTC without conjunction with my timezone.
I've even checked it with SQLite (using the SELECT strftime('%s',timestring);) and got the correct milliseconds. Why then I got it incorrectly generated by those two statements I posted above? Thanks a lot in advance.
Three things to consider
Java doesn't support UTC with leap seconds, only GMT. This is because OSes don't support it.
Your milli-seconds will be inaccurate unless you get the time off a satellite synchronized device.
You cannot run the command at exactly the same time so they will different some of the time.
But more importantly than that, if you don't set the tiemzone it will use the default time zone.
SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);
// no time zone set so the default is used.
String lastModifiedTime = sdf.format(time);
Instead you should add
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Adding a 'Z' to the format will change the timezone no more than adding 'T' to the format, it is just a letter you added.
If you want the date format to format the time in the UTC zone, then use
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Related
-1800000 - 04:00
-19800000 - 05 : 00
I have highlighted the int values I am getting from the code. The actual values are given. I want to write code to convert these long Integer values into HH:MM format.
The real problem is that neither you nor I understand which conversion is expected here. I cannot solve that for you. I’d like to share a thought, though, it may be that it may help you a bit on the way.
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
long longValue = -1_800_000;
String formattedTime = Instant.ofEpochMilli(longValue)
.atZone(ZoneId.of("Asia/Kabul"))
.format(timeFormatter);
System.out.println(formattedTime);
This prints the expected.
04:00
I am assuming that the long value denotes milliseconds since the epoch, this would be very commonplace. It agrees with the local time in Asia/Kabul and Asia/Tehran time zones, I don’t know whether there are other time zones that may fit.
If this explanation is to hold, we will have to assume that there is a bug in the other value, though. I could not find a time zone where that value would fit with a time of 05:00. Also if the values belong to different time zones, you don’t stand a chance unless they are telling which time zones they are.
public static String getDate(long time) {
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
cal.setTimeInMillis(time);
SimpleDateFormat month_date = new SimpleDateFormat("HH:MM");
String date = month_date.format(cal.getTime()).toString();
System.out.println(date);
return date;
}
This give me the answer but there is a variation of one or two mins
I'm trying to create a java.sql.Time object to query time types in an SQL database, but I'm using joda to parse the string that I receive.
I've tried a few different approaches. This is my most recent.
protected Time startTime = null;
protected static final String dateFormat = "HH:mm:ssZ";
protected static final DateTimeFormatter formatter = DateTimeFormat.forPattern(dateFormat);
public TimeBetweenFilter(String fieldName, String type, String value) {
super(fieldName, type, value);
String [] times = value.split("\\|");
if(times.length == 2 && !times[0].isEmpty() && !times[1].isEmpty()){
try{
LocalDateTime current = LocalDateTime.now();
LocalDateTime timeFromEpoch= new LocalDateTime(formatter.parseDateTime(times[0]));
startTime = new Time(timeFromEpoch.withDate(current.getYear(), current.getMonthOfYear(), current.getDayOfMonth()).toLocalTime().toDateTimeToday().getMillis());
}catch (Exception e){
...
}
But the output is always 1 hour behind the input received. For instance, if the input is 10:30:00 in UTC, startTime should be 4:30:00 local time. But instead I get 3:30.
Solved
DateTime beginning = new DateTime(DateTimeZone.UTC).toDateMidnight().toDateTime().plus(DateTime.parse(times[0], formatter).getMillis());
startTime = new Time(beginning.getMillis());
Creates a new date, this morning at midnight with time zone UTC, then adds the UTC time of day in milliseconds. Then it's converted to a java.sql.Time object.
A LocalDateTime doesn't logically have any time zone or DST information. That's the whole point - it's "local" but not to any specific time zone. Two people in different time zones might both wake up at the same local date/time, but that doesn't mean they're the same instants.
If you need a type which includes a time zone, you should be using DateTime.
EDIT: Okay, one approach is to take "today in the local time zone", parse the time to a LocalTime, combine the two to form a LocalDateTime, convert that to a DateTime in UTC, then convert that DateTime to the local time zone instead. The difficulty is that the end dates may not be the same, in which case you may need to add or subtract a day. That could then change the time of day due to DST changes, which makes it harder still. There are likely to be nasty corner cases to consider.
It feels like your requirement is odd to start with though - it's odd to have just a time which is in UTC, which you want to use in a date/time in the local time zone. Perhaps if you gave some more context, that would help.
I want to get the current UTC time in millis. I searched google and got some answers that System.currentTimeMillis() does returns UTC time. but it does not. If I do following:
long t1 = System.currentTimeMillis();
long t2 = new Date().getTime();
long t3 = Calendar.getInstance().getTimeInMillis();
all three times are almost same ( difference is in milli seconds due to calls ).
t1 = 1372060916
t2 = 1372060917
t3 = 1372060918
and this time is not the UTC time instead this is my timezone time. How can i get the current UTC time in android?
All three of the lines you've shown will give the number of milliseconds since the unix epoch, which is a fixed point in time, not affected by your local time zone.
You say "this time is not the UTC time" - I suspect you've actually diagnosed that incorrectly. I would suggest using epochconverter.com for this. For example, in your example:
1372060916 = Mon, 24 Jun 2013 08:01:56 GMT
We don't know when you generated that value, but unless it was actually at 8:01am UTC, it's a problem with your system clock.
Neither System.currentTimeMillis nor the value within a Date itself are affected by time zone. However, you should be aware that Date.toString() does use the local time zone, which misleads many developers into thinking that a Date is inherently associated with a time zone - it's not, it's just an instant in time, without an associated time zone or even calendar system.
I can confirm that all three calls could depend on the local time, considering the epoch, not the Date.toString() or any similar method. I've seen them depend on local time in specific devices running Android 2.3. I haven't tested them with other devices and android versions. In this case, the local time was set manually.
The only reliable way to get an independent UTC time is requesting a location update using the GPS_PROVIDER. The getTime() value of a location retrieved from NETWORK_PROVIDER also depends on local time. Another option is ping a server that returns a UTC timestamp, for example.
So, what I do is the following:
public static String getUTCstring(Location location) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String date = sdf.format(new Date(location.getTime()));
// Append the string "UTC" to the date
if(!date.contains("UTC")) {
date += " UTC";
}
return date;
}
I searched topics about formatting time but these were all about Date class or DateTime. I am working with Time class. I created time as:
Time time = new Time(Time.getCurrentTimezone()) ;
time.setToNow();
String berkay = time.toString();
System.out.println(berkay);
When I execute it the output is :
20130417T070525GMT(3,106,0,0,1366182325)
actually date and time is correct (2013-04-17 07:05:25)
but I need to convert it into : 20130417070525 (My reason to do this is I will search database according to date so it is easier to compare times in that format)
How can I convert it?
Try this:
Time time = new Time(System.currentTimeMillis()) ;
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String date = df.format(time).toString();
System.out.println(date);
EDIT
But as smttsp suggested its much more efficient to store it as timestamp
To convert java.util.Date into String you should consider java.text.SimpleDateFormat.
For using java.util.Date as a parameter of a database query you should pass the Date as is without converting it into any other format.
passing Date parameter to create date range query
<- In the answer there is sample how to create such query.
It is a bit late but if you are working on time and you need to compare or sort, the best way is to use Unix timestamp. It starts from 1-Jan-1970 00:00:00 and increments 1 each second.
It is a long value(64 bit) which is quite efficient to use in both time and space. Here is the website for Unix timestamp conversion.
Also 20130417070525 is 14 char string(at least 15 byte, I guess) and 1366182325 is long(8 byte). So go for long value. U can get it in that way
Date myDate = new Date(); // current time
myDate.getTime(); // converts it to specified format.
In my web app, date & time of a user's certain activity is stored(in database) as a timestamp Long which on being displayed back to user needs to be converted into normal date/time format.
(Actually my database Cassandra stores the timestamp of when a column was written to it, as a long value( microseconds since 1970 ) which I will use to find out the time of that corresponding user activity)
I am using JSF 2.0(+ primefaces) which I believe has converters that may be helpful for this conversion? Or otherwise how How can I, at best, achieve these conversions?
Let me propose this solution for you. So in your managed bean, do this
public String convertTime(long time){
Date date = new Date(time);
Format format = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
return format.format(date);
}
so in your JSF page, you can do this (assuming foo is the object that contain your time)
<h:dataTable value="#{myBean.convertTime(myBean.foo.time)}" />
If you have multiple pages that want to utilize this method, you can put this in an abstract class and have your managed bean extend this abstract class.
EDIT: Return time with TimeZone
unfortunately, I think SimpleDateFormat will always format the time in local time, so we can't use SimpleDateFormat anymore. So to display time in different TimeZone, we can do this
public String convertTimeWithTimeZome(long time){
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.setTimeInMillis(time);
return (cal.get(Calendar.YEAR) + " " + (cal.get(Calendar.MONTH) + 1) + " "
+ cal.get(Calendar.DAY_OF_MONTH) + " " + cal.get(Calendar.HOUR_OF_DAY) + ":"
+ cal.get(Calendar.MINUTE));
}
A better solution is to utilize JodaTime. In my opinion, this API is much better than Calendar (lighter weight, faster and provide more functionality). Plus Calendar.Month of January is 0, that force developer to add 1 to the result, and you have to format the time yourself. Using JodaTime, you can fix all of that. Correct me if I am wrong, but I think JodaTime is incorporated in JDK7
java.time
ZoneId usersTimeZone = ZoneId.of("Asia/Tashkent");
Locale usersLocale = Locale.forLanguageTag("ga-IE");
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
.withLocale(usersLocale);
long microsSince1970 = 1_512_345_678_901_234L;
long secondsSince1970 = TimeUnit.MICROSECONDS.toSeconds(microsSince1970);
long remainingMicros = microsSince1970 - TimeUnit.SECONDS.toMicros(secondsSince1970);
ZonedDateTime dateTime = Instant.ofEpochSecond(secondsSince1970,
TimeUnit.MICROSECONDS.toNanos(remainingMicros))
.atZone(usersTimeZone);
String dateTimeInUsersFormat = dateTime.format(formatter);
System.out.println(dateTimeInUsersFormat);
The above snippet prints:
4 Noll 2017 05:01:18
“Noll” is Gaelic for December, so this should make your user happy. Except there may be very few Gaelic speaking people living in Tashkent, so please specify the user’s correct time zone and locale yourself.
I am taking seriously that you got microseconds from your database. If second precision is fine, you can do without remainingMicros and just use the one-arg Instant.ofEpochSecond(), which will make the code a couple of lines shorter. Since Instant and ZonedDateTime do support nanosecond precision, I found it most correct to keep the full precision of your timestamp. If your timestamp was in milliseconds rather than microseconds (which they often are), you may just use Instant.ofEpochMilli().
The answers using Date, Calendar and/or SimpleDateFormat were fine when this question was asked 7 years ago. Today those classes are all long outdated, and we have so much better in java.time, the modern Java date and time API.
For most uses I recommend you use the built-in localized formats as I do in the code. You may experiment with passing SHORT, LONG or FULL for format style. Yo may even specify format style for the date and for the time of day separately using an overloaded ofLocalizedDateTime method. If a specific format is required (this was asked in a duplicate question), you can have that:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss, dd/MM/uuuu");
Using this formatter instead we get
05:01:18, 04/12/2017
Link: Oracle tutorial: Date Time explaining how to use java.time.
Not sure if JSF provides a built-in functionality, but you could use java.sql.Date's constructor to convert to a date object: http://download.oracle.com/javase/1.5.0/docs/api/java/sql/Date.html#Date(long)
Then you should be able to use higher level features provided by Java SE, Java EE to display and format the extracted date. You could instantiate a java.util.Calendar and explicitly set the time: http://download.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html#setTime(java.util.Date)
EDIT: The JSF components should not take care of the conversion. Your data access layer (persistence layer) should take care of this. In other words, your JSF components should not handle the long typed attributes but only a Date or Calendar typed attributes.
To show leading zeros infront of hours, minutes and seconds use below modified code. The trick here is we are converting (or more accurately formatting) integer into string so that it shows leading zero whenever applicable :
public String convertTimeWithTimeZome(long time) {
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.setTimeInMillis(time);
String curTime = String.format("%02d:%02d:%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
return curTime;
}
Result would be like : 00:01:30
I tried this and worked for me.
Date = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1, 0, 0, 0))).TotalSeconds