My Objective is
to create a java class that can handle the below two requirements
(A) 1. Verify if the format of a timestamp matches with expected format.
CCYY-MM-DD'T'hh:mm:ss'.0000000000+'uh:um"
Ex: the expected format
is not static. It may be either of these
"2013-09-10T18:30:20.123456+10:00" or
"2013-09-10T18:30:20.123+10:00".
I am not bothered about the
precision and value. Only the format matters.
(B) 2. Verify if the timestamp is in a certain range.
Ex: Verify if the timestamp is in between "2013-09-10 18:27" and "2013-09-10 18:33". (verification is only upto minute level precision) (may be a delta of + or - 2min)
The question on first objective was posted here
Java : Custom Timestamp Format : verify format to microsec precision
In refrence to the second objective :
The Question :
How to verify if the timestamp is within the given range to minute precision using Java class?
The inputs to the class will be three arguments
The timestamp to be verfied as a string
The lower range timestamp as string
the higer range timestamp as string.
I tried this
String date = "2013-09-10T18:30:12.123456789+10:00"
SimpleDateFormat df2 = new SimpleDateFormat("yyyyMMddHHmm");
date = date.substring(0,22)+"+10:00";
Date newDate = df.parse(date);
timestamp_value = df2.format(newDate);
timestamp_value is now 201309101830
Check if timestamp_value is greater than 201309101827.
Check if timestamp_value is lesser_ than 201309101833
This is okay.
However, i feel this i a crude way of achieving it, so I would like to know if there is any better solution.
If i could convert to Timestamp object, i think .before and .after can help. Any suggestions ?
1) "2013-09-10T18:30:20.123+10:00" is XSD dateTime format and the best way to parse it is this
XMLGregorianCalendar xgc = javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar(date);
if date format is wrong IllegalArgumentException will be thrown
2) to verify if a timestamp is within a certain range the easiest way is to get millis from dates, truncate to minutes and use arithmetic comparison t >= from - delta && t <= to + delta
Related
My Objective is
to create a java class that can handle the below two requirements
(A) 1. Verify if the format of a timestamp matches with expected format.
CCYY-MM-DD'T'hh:mm:ss'.0000000000+'uh:um"
Ex: the expected format is not static.
It may be either of these
"2013-09-10T18:30:20.123456+10:00" or
"2013-09-10T18:30:20.123+10:00".
I am not bothered about the
precision and value. Only the format matters.
(B) 2. Verify if the timestamp is in a certain range.
Ex: Verify if the timestamp is in
between "2013-09-10 18:27" and "2013-09-10 18:33". (verification is only upto minute level precision) (may be a delta of + or - 2min)
As suggested by one of the member, I have edited the post to target at
One specific question.
The QUESTION :
How to validate the custom timestamp upto microsec precision using JAVA class ?
The two arguments for this class will be
1) Expected FORMAT as a String
2) timestamp value as a String
Based on analysis from various search results, below is my understanding :
Java (by default) does not parse/format Timestamp at microsecond level( I used SimpleDateFormat)
If 6 digits are given in milliseconds place, it will re-calculate the value into seconds and the dateformat will be updated and the new dateformat will have 3 digits in milliseconds precision.
I have also seen a thread which suggests to use java.sql.Timestamp.
Tried this approach but not working.
I was not able to convert my strTimestamp 2013-09-10T18:30:20.123456+10:00 into Timestamp object.
Timestamp ts = Timestamp.valueOf(strTimestamp);
java.lang.IllegalArgumentException:
Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
I was not able convert my input format into Timestamp object.
I have a workaround to validate using regular expression :
2013-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9]).[0-9][0-9][0-9][0-9][0-9][0-9]\+10:00
The problem with this reg ex is that, my expected timestamp format is not static. So i have to use a regex for every pattern.
So I am trying to figure out if there is any robust solution in java, which can be self sufficient even if the expected format changes.
java.time in Java 8
JSR 310 defined a new java.time package in Java 8. Its date-time class resolves to nanoseconds. That gives you 9 digits after the decimal point.
The java.time package is inspired by Joda-Time but entirely re-architected. Concepts are similar.
Like Joda-Time, the java.time package uses ISO 8601 formats as its defaults for parsing and formatting. So you can input or output strings such as 2013-09-10T18:30:20.123456789+10:00.
An early release of Java 8 is available now. Official release should be this month.
A project to backport this package to earlier versions of Java was underway. I do not know of its current status or success. The backport project is independent of Oracle and the OpenJDK project.
Milliseconds
The old bundled classes, java.util.Date & .Calendar, use a precision of milliseconds.
Ditto for the excellent Joda-Time library, milliseconds precision.
So not enough digits in the fractional seconds to meet your needs.
A java.sql.Timestamp is not going to help you, because that is a java.util.Date.
The code is fairly simple, if you use the right format String with SimpleDateFormat, which you let do the heavy lifting. Here's an entire working solution:
public static boolean isNear(String timestamp, int microPlaces, Date near, int minutes) {
if (!timestamp.matches(".*\\.\\d{" + microPlaces + "}\\D.*") {
return false;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ");
try {
Date date = sdf.parse(timestamp.replaceAll(":(?=\\d\\d$)", ""));
return Math.abs(date.getTime() - near.getTime()) <= minutes * 60000;
} catch (ParseException ignore) {
return false; // string was not of correct format
}
}
This may not be exactly what you had in mind - if not, you should be able to use it as a basis for what you want. The key points are:
The S format string means "microseconds", and it doesn't require all the digits - so your timestamp can have any number
Java 6 needs the colon removed from the timezone. Java 7 doesn't need this - use the X format string instead of Z
A failure to parse a date from the input throws a ParseException - do what you want with this event
I chose to make the API give central date for the range and a +/- minute value. You may need to pass two dates - up to you. Use Date.before() and Date.after() to compare if you do that.
Here's some test code testing your examples and a couple of edge cases:
public static void main(String[] args) throws Exception {
Date near = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm").parse("2013-09-10T18:32");
System.out.println(isNear("2013-09-10T18:30:20.123456+10:00", near, 2));
System.out.println(isNear("2013-09-10T18:30:20.123+10:00", near, 2));
System.out.println(isNear("2013-09-10T18:10:20.123+10:00", near, 1));
System.out.println(isNear("XXXX-09-10T18:10:20.123+10:00", near, 1));
}
Output:
true
true
false
false
Really I`m also trying to find answer to this problem. As I have no ability to add comment to the Bohemian answer. I want to mention that 'S' pattern in SimpleDateFormat is used not for microseconds but for milliseconds. It means that for pattern "yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ" provided microsecond digits in string would be parsed as milliseconds.
So the first three digits would be passed as XXX seconds and their value value would be added to date. So we can receive mistake about 16 minutes.
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.
I have a file I want to encrypt and decrypt based on a date. When writing it, I want to use the current date, but not the time. What would I use for this?
Then, whenever I want to decrypt it, I can just use File.lastModified to get the long date. From here, how do I convert this into only the date (and not the time) it was written (or last modified, which should be the same)?
I would prefer to avoid extra libraries, and if it's overly complex, that's fine because I am encrypting data and complex code would help throw off snoopers. Most of all, it needs to be able to read the date across all locales and platforms in the same manner, so as to not throw off the encryption.
EDIT: URL problem solved. Java wanted a / in between .net and ? in the following:
"http://login.minecraft.net/?user=" + username + "&password=" + password + "&version=99"
Now my encryption class is flipping out over something...
Simple suggestion: first convert the date to a yyyy-mm-dd string. Second hash the string along with any other relevant data you need to make your key. See Convert timestamp long to normal date format for long/date to string conversion.
GregorianCalendar c = new GregorianCalendar(time);
c.set(GregorianCalendar.HOUR, 0);
c.set(GregorianCalendar.HOUR_OF_DAY, 0);
c.set(GregorianCalendar.MINUTE, 0);
c.set(GregorianCalendar.SECOND, 0);
c.set(GregorianCalendar.MILLISECOND, 0);
c.getTimeInMillis();
The long time value is defined as:
A milliseconds value represents the number of milliseconds that have passed since January 1, 1970 00:00:00.000 GMT.
So to round down to the nearest day you need something like:
public static final long OneDay = 1000l * 60l * 60l * 24l;
long today = (System.currentTimeMillis() / OneDay) * OneDay;
Date lastMidnight = new Date(today);
But please do not forget potential time zone issues.
I have a certain value of date and time say 28-3-2012(date) - 10:36:45(time) . I wish to convert this whole timestamp to nanoseconds with the precision of nanoseconds. As in the user would input the time and date as shown but internally i have to be accurate upto nanoseconds and convert the whole thing to nanoseconds to form a unique key assigned to a specific object created at that particular time.
Could some one please help me with the same..
The precision of the sample date is seconds, the representation in long format is a value in millisecond units. You can convert that to nanosecond units by multiplying it with 1,000,000.
But, in fact, it will simply append nine zeros to the oririginal date value and not add any extra information that you'd need to create hashvalues. A Date object has no "hidden" nanosecond precision.
Java offers the method System.nanoTime() which returns a timevalue in nano second units. But we can't wrap it in a Date object without loosing precision. Nevertheless, it may help in your case to create unique "time values".
if you have Date object:
long nanosecond = date.getTime() * 1000000;
or you can parse your time string if its look like (dd/MM/yyyy HH:mm:ss)
DateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = df.parse(dateString);
long nanosecond = date.getTime() * 1000000;
I suppose the simplest way would be to use JDK's support for this. Try following
TimeUnit.NANOSECONDS.toNanos(duration)
Here the single parameter duration will be the long value to which you want to convert to NanoSeconds.
Hope this helps.
This is general programming, but I'm working in Java.
Given a date dd-mm-yy or dd-mm-yyyy (e.g. 13-01-2011) I want to convert this into a unique number such that any two dates have a different number. And the year isin't important. So just converting dd-mm into one unique int is acceptable. Does anyone know an algorithm for doing this?
I'm SOrry: I want to be more specific:
The unique numbers should be from 1 to 365 (or 0 to 364), or should break down uniquely modulo 365. (I'm ignoring the case of leap years at the moment).
So concatenating "ddmm" might be a unique 4 digit number. But modulo 365 probably wouldnt be unique.
So you basically want to get the day of year? That's not the same as "an unique int from date".
Use Calendar#get(Calendar.DAY_OF_YEAR) (which is 1-based).
Date date = getItSomehow();
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
As you already admitted, comparing this on leap/non-leap years will fail.
Use the number of days since the beginning of the year.
new Date().getTime()
The number of milliseconds since 1970 should be unique to each date. Just convert the string to a date object and use getTime()
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
Date date = formatter.format( myInput );
Use unix timestamp see java.util.Date.getTime()
If you just need a unique key, Calendar's hashCode() should do the trick.
Alternately, you can concatenate the two digit month and day, and four digit year.
Update: the OP clarified the question to want a unique value in the range 1-364. In that case I would convert the date into a Calendar object and call get (Calendar.DAY_OF_YEAR) on it - this will return the number of the day within the year, which is exactly what the OP is after it seems.
Original answer:
There about as many ways to do this as there are bits of string. If you want to be able to use the unique numbers for relative comparison of dates then the most obvious solution is to do what most computers do anyway, namely convert the date into some lowest common denominator, like the number of seconds from a particular epoch. Java provides ways for doing this with both the Date and Calendar classes. If you only care about days and months, you could achieve the same with something like int v = (month * 120) + day. If you don't care about comparisons and just want a unique value, you could come up with a digest of the date using a hashing algorithm of some kind. In Java you could, for example, take a String representation of the date and call hashCode() on it.