I have defined a object model where one of the array elements is a string
public static String[] columnNames6
= {"Total Shares",
"Total Calls",
"Call Strike",
"Call Premium",
"Call Expiry"
};
public static Object[][] data6
= {
{ new Double(0), new Double(0), new Double(0), new Double(0),"dd/mm/yyyy"},
};
I then use the following code to get the date so that I can use the data method but having
no joy - Can someone please tell me why it is throwing an exception after I do this
String ExpiryDate = (String)GV.data6[0][4];
System.out.println("DATE STRING IS: " + ExpiryDate);
Date EndOptionDate = new Date(ExpiryDate); // SOMETHING WRONG HERE even though it compiles okay
//Get Todays's Date
Date TodaysDate = new Date();
//Calculate Days Option Expiry
long DaysDifference = EndOptionDate.getTime() - TodaysDate.getTime();
Would really appreciate some help as really stuck not sure how I should code the
line in bold - new to java, so please excuses my lack of knowledge looked at tutorials
can't seem to move forward.
Thanks
Simon
ExpiryDate is a string try changing it to a date, its deprecated
Date(String s)
Deprecated. As of JDK version 1.1, replaced by DateFormat.parse(String s).
Here's an example:
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
Date today = df.parse("25/12/2010");
System.out.println("Today = " + df.format(today));
As said by JonH, you should use DateFormat.parse instead of new Date(String). Beside, your calculation of date difference is probably not good either:
//Calculate Days Option Expiry
long DaysDifference = EndOptionDate.getTime() - TodaysDate.getTime();
Will give you the difference in milliseconds between the two dates, not in days. You can use TimeUnit like this to obtain the day difference:
long dayDiff = TimeUnit.MILLISECONDS.toDays(EndOptionDate.getTime() - TodaysDate.getTime());
Related
we run a REST-webservice which consumes different data, my current issue belongs to a date, received as String and parsed by a java.text.SimpleDateFormat (java 8):
We received a lot (>50k) of 'wrong' formatted Strings, which were parsed by the SimpleDateFormat anyways.
The SimpleDateFormat is configured with the pattern "yyyy-MM-dd".
We received Strings the other way around "dd-MM-yyyy".
For Example the String "07-07-1950" was parsed to the date "0012-10-31" (Starting from July in year 7, added 1950 days).
We fixed the implementation, so these Strings are now parsed as expected. But we have all the corrupt dates in the system. The final question is now:
Is there a way to conclude from the date "0012-10-31" to possible original inputs (e.g. "07-07-1950", "07-06-1980" and maybe more...)?
Best regards
I found a way to find possible inputs:
I can use Calendar to iterate through possible dates, parsing the dates in the "wron"g way, and build a map with these information.
public static Map<String, Collection<String>> createDateMapping() throws ParseException
{
final DateFormat targetFormat = new SimpleDateFormat("yyyy-MM-dd");
final DateFormat wrongFormat = new SimpleDateFormat("dd-MM-yyyy");
//starting today
final Calendar cal = Calendar.getInstance();
final Map<String, Collection<String>> inputMappings = new HashMap<>();
//rolling down to year zero is quite time consuming, back to year 1899 should be enough...
while (cal.get(Calendar.YEAR) > 1899)
{
//creating the "wrong" date string
final String formattedDate = wrongFormat.format(cal.getTime());
final String key = targetFormat.format(targetFormat.parse(formattedDate));
if (!inputMappings.containsKey(key))
{
inputMappings.put(key, new ArrayList<>());
}
inputMappings.get(key).add(targetFormat.format(cal.getTime()));
//roll calendar to previous day
cal.roll(Calendar.DAY_OF_YEAR, false);
if (cal.get(Calendar.DAY_OF_YEAR) == 1)
{
//roll down the year manually, since it is not rolled down automatically
cal.roll(Calendar.DAY_OF_YEAR, false);
//roll down the day again, to start at the last day of the year again
cal.roll(Calendar.YEAR, false);
}
}
return inputMappings;
}
by the use of this method I can:
final Map<String, Collection<String>> dateMapping = createDateMapping();
System.out.println(dateMapping.get("0012-10-31"));//[2011-05-07, 1980-06-07, 1950-07-07, 1919-08-07]
It will not solve the problem completely, but is at least a good starting point - hopefully there are some dates with more explicit results.
Building on Martin Ackermann's answer:
First of all, I simplified the code a bit.
public static Map<String, Set<LocalDate>> createDateMapping(LocalDate min, LocalDate max) throws ParseException {
DateFormat targetFormat = new SimpleDateFormat("yyyy-MM-dd");
DateTimeFormatter wrongFormat = DateTimeFormatter.ofPattern("dd-MM-yyyy");
final Map<String, Set<LocalDate>> inputMappings = new LinkedHashMap<>();
for (LocalDate date = min; !date.isAfter(max); date = date.plusDays(1)) {
final String incorrectlyFormattedDate = date.format(wrongFormat);
final String key = targetFormat.format(targetFormat.parse(incorrectlyFormattedDate));
if (!inputMappings.containsKey(key)) {
inputMappings.put(key, new TreeSet<>());
}
inputMappings.get(key).add(date);
}
return inputMappings;
}
Easily fixing the invalid dates depends on what is the range of valid dates.
For example if max=2016-12-31 then the following table shows the number of unique dates that are fixable/ambiguous depending on min
min fixable ambiguous
-----------------------------
1990-01-01 9862 0
1980-01-01 8827 2344
1970-01-01 5331 5918
1960-01-01 1832 9494
1950-01-01 408 10950
1940-01-01 314 11054
1930-01-01 218 11160
1920-01-01 165 11223
1910-01-01 135 11263
1900-01-01 105 11303
Ambiguous matches for invalid dates occur at about 30 year intervals so if the actual dates fall in a period of 30 years then you are in luck
LocalDate max = LocalDate.of(2016, Month.DECEMBER, 31);
LocalDate min = max.minusYears(30);
Map<String, Set<LocalDate>> invalidDateMapping = createDateMapping(min, max);
long reversibleCount = invalidDateMapping.entrySet().stream().filter(e -> e.getValue().size() == 1).count(); // 10859
long ambiguousCount = invalidDateMapping.size() - reversibleCount; // 50
I don't think you will be able to figure out the original date of the corrupted input, but you should be able to find all corrupted dates and perhaps find a way to re-consume that data. This is because each date was altered by an unknown number of days, and reversing that process would require you to know either the number of days or the starting date, and it looks like you don't have that here.
That said, it will actually be fairly easy to narrow down any dates that were corrupted.
The largest value you will be given for a month should be 12. That means the latest "year" for your corrupted data will be the year 12. If your dates run right up to the present, the largest year (which was incorrectly parsed as days) will be 2016, which would be converted to about 5.5 years. So any dates with years below 18 or 19 are corrupted, and you should be able to at least remove them.
The only edge case here is if you have dates that have years that will validly land in the early teens. If that's the case, you'd have to go through those by hand. But that seems unlikely.
Have you tried setting SimpleDateFormat Lenient to false
package test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
public static void main(String[] args) throws ParseException {
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat dateFormat2 = new SimpleDateFormat("dd-MM-yyyy");
dateFormat1.setLenient(false);
dateFormat2.setLenient(false);
Date d = null;
String invalidDate = "07-06-1980";
try {
d = dateFormat1.parse(invalidDate);
} catch (Exception e) {
System.out.println("reversed date " + invalidDate);
d = dateFormat2.parse(invalidDate);
}
System.out.println(parsed date " + dateFormat1.format(d));
}
}
reversed date 07-06-1980
parsed date 1980-06-07
Simply, I'm storing an 'initial date' data as a String variable in a text file e.g. 02-02-2015, and I just need to know if 3 days has passed from that initial date. I've been recommended to use JodaTime but I kept on recieving errors with it which I'm presuming is because I'm comparing String and Int variables.
Is this possible, if so how? Thanks in advance?
EDIT: Apologies I didn't post the code.
public void startDelay() {
DateTime dt = new DateTime();
DateTimeFormatter fmt = DateTimeFormat.forPattern("dd-MM-yyyy");
delayPin = fmt.print(dt);
}
public int delayEnded() {
DateTime dt = new DateTime();
DateTimeFormatter fmt = DateTimeFormat.forPattern("dd-MM-yyyy");
String today = fmt.print(dt);
delayProgress = Days.daysBetween(new DateTime(delayPin), new DateTime(today)).getDays();
return delayProgress;
}
delayPin is being stored in the text file. I repeated the method to get todays date within the second delayEnded method.
Something like this?
String storedDateString = "02-02-2015";
DateTimeFormatter format =
new DateTimeFormatterBuilder().appendPattern("MM-dd-yyyy").toFormatter();
Boolean isThreeDaysPassed =
LocalDate.now().minusDays(3).isAfter(LocalDate.parse(storedDateString, format));
Ok, so what I'm trying to do is to set the set the date of a calendar instance, and then return the week_of_year. I am doing so by using the Calendar.set() functio
public String weekInYearForm = "ww";
SimpleDateFormat formWIM = new SimpleDateFormat(weekInYearForm, Locale.US);
Calendar lc = Calendar.getInstance();
lc.set(Calendar.YEAR, lYear);
lc.set(Calendar.MONTH, lMonth);
lc.set(Calendar.DAY_OF_MONTH, lDay);
wiy = formWIM.format(lc.get(Calendar.WEEK_OF_YEAR));
To get the lYear, lMonth, and lDay values, I am passing a string in the format 04/26/2013 to through the following steps:
String[] arrDate = dateIn.split("/");
int lMonth = Integer.parseInt(arrDate[0]) - 1;
Log.d("SaveHandler", "Month is: " + lMonth);
int lDay = Integer.parseInt(arrDate[1]);
Log.d("SaveHandler", "Day is: " + lDay);
int lYear = Integer.parseInt(arrDate[2]);
Log.d("SaveHandler", "Year is: " + lYear);
The problem I am facing is that when I look at what is outputed to wiy, it is always 1. Upon some further debugging, I realized that the time is being left at epoch time, and not setting to the values I need.
I also tried using lc.set(lYear, lMonth, lDay), also to no avail. If anyone has any ideas, I would greatly appreciate them.
*EDIT: I did some debugging earlier and it is returning 1970 for the year and 0 for the month.
use
formWIM.format(lc.getTime());
instead of
formWIM.format(lc.get(Calendar.WEEK_OF_YEAR));
EDIT
You can parse your date (instead of dateIn.split( etc.)
SimpleDateFormat monthDayYear = new SimpleDateFormat("MM/dd/yyyy", Locale.US); //04/26/2013
Date date = monthDayYear.parse("04/26/2013");
and then format it
SimpleDateFormat formWIM = new SimpleDateFormat("ww", Locale.US);
formWIM.format(date);
This code is correct, the problem is in formWIM.format(...) or the battery of your motherboard clock is drained.
I have a little problem with the translation of this data 19/12/2005
17:30:45 to mileseconds. I don't know why, I am getting a wrong translation to Jun 28 17:30:45 CEST 1995 Time :804353445798
The code I used is this :
private static long ConvertTimeToTimeStamp(String time) {
Integer[] data = new Integer[6];
String [] tokens = time.split(" ");
System.out.println(tokens[0]);
System.out.println(tokens[1]);
String[] d_m_y = tokens[0].split("/");
String[] hh_mm_ss = tokens[1].split(":");
for (int i = 0; i < d_m_y.length; i++) {
data[i]=Integer.parseInt(d_m_y[i]);
// System.out.println(d_m_y[i]);
}
for (int i = 0; i < hh_mm_ss.length; i++) {
data[i+3]=Integer.parseInt(hh_mm_ss[i]);
// System.out.println(hh_mm_ss[i]);
}
//Calendar calendar = Calendar.getInstance();
GregorianCalendar calendar = new GregorianCalendar();
calendar.set(data[0]+1970, data[1], data[2], data[3],data[4],data[5]);
System.out.println(calendar.getTime().toString());
return calendar.getTimeInMillis();
}
You should not parse the date manually - use a date format instead:
String s = "19/12/2005 17:30:45";
Date d = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").parse(s);
Treat this object from the outset as a date. That will be much more reliable.
Use SimpleDateFormat.parse() to parse your string into a date/time. Otherwise you're reduced to string parsing/splitting/recombining etc with no bounds-checking, type-checking etc. Your solution is stringly-typed, not strongly-typed.
I've referenced the standard Java libraries, but Joda-Time is a better bet for doing date work in Java and I would advise adopting this for a more intuitive and safer API.
Forget about it. Use a SimpleDataFormat object with pattern dd/MM/yyyy HH:mm:ss to parse() the String into a date object.
try...
private static long ConvertTimeToTimeStamp(String time) {
//19/12/2005 17:30:45
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
java.util.Date d = sdf.parse(time);
return d.getTime();
}
You are mixing the order of year, month and day. The set method is expecting them in the following order: year, month, day and you are providing them as day + 1970, month, year.
Having said that, you might actually be much more happy with a library like joda-time.
I have a requirement where I have to convert timezone from UTC to a specific timezone and vice-versa taking into account day light saving. I am using java.util.TimeZone class for it. Now, issue is that there are several hundred Ids for timezone which cannot be displayed to user.
As a work around now we have decided to have country list first and list time-zones for country selected. I am not able to get TimeZone for an ISO country code.
Here is code which I am currently using to convert timezones,
Timestamp convertedTime = null;
try{
System.out.println("timezone: "+timeZone +", timestamp: "+timeStamp);
Locale locale = Locale.ENGLISH;
TimeZone destTimeZone = TimeZone.getTimeZone(timeZone);// TimeZone.getDefault();
System.out.println("Source timezone: "+destTimeZone);
DateFormat formatter = DateFormat.getDateTimeInstance(
DateFormat.DEFAULT,
DateFormat.DEFAULT,
locale);
formatter.setTimeZone(destTimeZone);
Date date = new Date(timeStamp.getTime());
System.out.println(formatter.format(date));
convertedTime = new Timestamp(date.getTime());
/*long sixMonths = 150L * 24 * 3600 * 1000;
Date inSixMonths = new Date(timeStamp.getTime() + sixMonths);
System.out.println("After 6 months: "+formatter.format(inSixMonths));
I need to find out timezone Id to be used in above code for given country ISO code.
Update: tried many things and below code gets me to list of timezones with 148 entries (which is still large). Can any one please help me to shorten it. Or, suggest some other way to either have a shorten list of timezones or get timezones for a country,
Code:
public class TimeZones {
private static final String TIMEZONE_ID_PREFIXES =
"^(Africa|America|Asia|Atlantic|Australia|Europe|Indian|Pacific)/.*";
private List<TimeZone> timeZones = null;
public List<TimeZone> getTimeZones() {
if (timeZones == null) {
initTimeZones();
}
return timeZones;
}
private void initTimeZones() {
timeZones = new ArrayList<TimeZone>();
final String[] timeZoneIds = TimeZone.getAvailableIDs();
for (final String id : timeZoneIds) {
if (id.matches(TIMEZONE_ID_PREFIXES)) {
timeZones.add(TimeZone.getTimeZone(id));
}
}
Collections.sort(timeZones, new Comparator<TimeZone>() {
public int compare(final TimeZone a, final TimeZone b) {
return a.getID().compareTo(b.getID());
}
});
}
I think ICU4J package will help you.
You can shorten your list with hasSameRules()... this should reduce you selection to about 50:
iterate through -> file equal time zones -> choose the most recognizables
The country- list has to have about 200 entries with a whole lot of uninteresting ones such as Gibraltar or St Martin... don't like that idea
Was able to get things working. I have created own database table with all time-zones as appearing in windows OS and their corresponding TimeZone IDs. Conversion is done using java.util.TimeZone class.
Thanks Namal and Frank for your inputs.