I have some java code that parses a string and creates a Date object. On Linux, everything works fine, but on Windows it continuously starts at 19:00:00 rather than 00:00:00. Here is the code:
if(currTask != null) {
if((m = p0.matcher(currTask)).matches()) {
date = new Date(Long.valueOf(m.group(2)) - Long.valueOf(m.group(1)));
}
else if((m = p.matcher(currTask)).matches()) {
date = new Date(System.currentTimeMillis() - Long.valueOf(m.group(1)));
}
return padded(date.getHours())+":"+padded(date.getMinutes())+":"+padded(date.getSeconds());
}
The returned value is the problem on Windows. Is this some inconsistency with how one of Date's methods works on Windows as opposed to Linux? Thanks for your help.
Ken
Check that your time zone is the same on both platforms... my guess is that they're not. (Print out TimeZone.getDefault().getDisplayName() to see what the default is.)
However, you shouldn't be using Date.getHours()/getMinutes()/getSeconds()/getSeconds() anyway; they're deprecated. You could use Calendar... or you could bite the bullet and use Joda Time, which is a far superior date and time API.
What does your input look like and what's the result meant to be?
The difference must be in your locale. There are environment variables that affect this on Linux. Let me guess: you're in EST (GMT-5)?
Related
I have a date supplied by the user and of course today's date.
I'm attempting to verify that the difference between the 2 days is at least 2 weeks. I've done this using standard libraries - but I'm attempting to do this using jodaTime and I'm having some difficulty.
// BAD CODE - doesn't work
// NOTE: getUserSuppliedDate() returns an instance of java.sql.Date
// Also assume that validation prior to this call has been run that
// validates that the userSuppliedDate comes AFTER today's date - not sure if
// that is relevant in the context I'm attempting to use these particular jodaTime APIs.
DateTime jodaStartDate = new DateTime(getUserSuppliedDate());
if (Days.daysBetween(jodaStartDate, DateTime.now()).isLessThan(Days.days(14))) {
System.out.println("Bad user. You have chosen...poorly.");
}
else {
System.out.println("Well done user. You have supplied wisely.");
}
// GOOD CODE ---- ? Help =)
Your code gives you the wrong result because the dates supplied to Days.daysBetween() are in the wrong order. Since you specified that the user supplied date comes after the current date, your approach will result in a negative number of days.
It will work correctly if you switch the order, putting the earliest date first.
Compare the following two:
DateTime jodaStartDate = new DateTime().withYear(2018)
.withMonthOfYear(7)
.withDayOfMonth(5); // 15 days from now
System.out.println(Days.daysBetween(jodaStartDate, DateTime.now())); // "P-15D"
System.out.println(Days.daysBetween(DateTime.now(), jodaStartDate)); // "P15D"
In the first case, -15 days will evaluate to less than 14 days.
Using weeks instead of days, you'd run into the same problem:
System.out.println(Weeks.weeksBetween(jodaStartDate, DateTime.now())); // "P-2W"
System.out.println(Weeks.weeksBetween(DateTime.now(), jodaStartDate)); // "P2W"
Initial time=22:00:00,final time=23:59:59.
If the current time is, let's say 23:00:00 then I will get the success message otherwise error message will be shown. And I am comparing this time with the system time.
My code:
//retrieving the system time in string format
SimpleDateFormat sdfDate = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
String s=sdfDate.format(date);
//Initial and final predefined time
String ten ="22:00:00";
String twelve ="23:59:59";
//comparing with the system time
try{
if(s.compareTo("twelve")<0 && s.compareTo("ten")>0 ){
out.print("success");
}else{
out.print("failed");
}
}catch(Exception l){
System.out.println(l.toString());
}
I tried to check it when the system time was 23:45:00. I also confirmed the time by printing out.print(""+s);. But I got the failed message. I don't know my loop is working or not.
What can I do to fix this?
If you're comparing hours, don't use strings, use a proper type.
In Java you have:
Java >= 8: java.time.LocalTime
Java <= 7: org.threeten.bp.LocalTime (from external lib: http://www.threeten.org/threetenbp/)
In both you can do:
LocalTime ten = LocalTime.parse("22:00:00");
LocalTime twelve = LocalTime.parse("23:59:59");
// current time
LocalTime now = LocalTime.now();
// compare
if (now.isBefore(twelve) && now.isAfter(ten)) {
// succcess
}
To get the current time, you could also use the now method with a timezone (example: LocalTime.now(ZoneId.of("America/New_York"))), if you need the time at some specific place (now() without arguments will use the JVM default timezone).
Transforming the strings to a type that represents the data you're working with is much more reliable. Also note that this API makes the code much easier and more readable, with meaningful methods names such as isAfter and isBefore.
Comparing strings might work, but using the proper types works even better.
Try this:
if(s.compareTo(twelve) < 0 && s.compareTo(ten) > 0)
By putting quotes around twelve and ten, you're comparing to the strings "twelve" and "ten", and not referencing the variables twelve and ten that you defined ealier in the program.
I am currently making an auction program in Java, I am trying to work out deadlines, however my date keeps coming out as (7/04/2013 11:22), is there a way to use String.format to add a leading zero to this date when it is a one digit day?
String timeOne = Server.getDateTime(itemArray.get(1).time).toString()
It causes me a problem later on when I try to sub string it, and it is less than 17 characters long.
Thanks in advance, James.
#Leonard Brünings answer is the right way. And here's why your original code is the wrong way ... even if it worked.
The javadoc for Calendar.toString() says this:
"Return a string representation of this calendar. This method is intended to be used only for debugging purposes, and the format of the returned string may vary between implementations."
Basically you are using toString() for a purpose that the javadoc says you shouldn't. Even if you tweaked the output from toString(), the chances are that your code would be fragile. A change in JVM could break it. A change of locale could break it.
Simply use the SimpleDateFormat
import java.text.SimpleDateFormat;
Calendar timeOne = Server.getDateTime(itemArray.get(1).time)
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm")
System.out.println(sdf.format(timeOne.getTime()))
With this C code:
int a = time(NULL);
_daylight = 0;
_timezone = 0;
int b = time(NULL);
assert(a != b);
"a" and "b" will have different values (and not just because they are called a few milliseconds apart). The difference will be whatever the offset of your PC's timezone is from UTC time. Also, changing the _daylight and _timezone values effect pretty much every other function I might use in my C app -- I assume because they all respect that value.
Is there anything like that in Java, or specifically for Java on Android OS? I tried TimeZone.setDefault(), but that didn't change the value that System.currentTimeMillis() returned, so I assume it isn't going to have a "global" effect like the C variables.
I understand that System.currentTimeMillis() is different than time(), in that it "always" returns the number of millis since now and epoch, and the time() function allows you to get "false" (fudged) values that are adjusted according to these global variables you can set.
Just trying to emulate a legacy C app on Android OS. It clears those _timezone and _daylight values which pretty much means it ignores any timezones. So if a user running the app on the west coast enters a time of 3pm, and then they change their timezone settings, or a user on the est coast views that item, it will still show as 3pm.
I know I can use the Calendar object and other methods to make sure I do the proper conversions, but I'd rather just have an easy "I don't care about timezones" settings like I did in the C app and then truely not have to worry about them.
Edit: I would still like to hear what other options I have, but for now I came up with this Java code that I'll do my best to always use for any code that needs to mimic the C app:
// IMPORTANT: Use this function everywhere a Calendar object is needed, instead of calling
// Calendar.getInstance() directly. This returns the correct kludged time that matches
// what our PC application uses (_daylight=0, _timezone=0, time(NULL) in C)
public static Calendar GetCalendarInstance()
{
// Get the current UTC time
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
// Offset it by the system time zone offset.
// This mimics what the C time(NULL) function does when you set _timezone=0 and _daylight=0
cal.add(Calendar.MILLISECOND, TimeZone.getDefault().getOffset(cal.getTimeInMillis()));
return(cal);
}
Also, I did already find one place in my Android app that I need the real, not adjusted, system time (when using AlarmManager to schedule a PendingIntent). So I guess "global" could be dangerous either way. I still think 95% of my code will be using the version that mimics the C app though, so if possible I'd like to default to that and then only have to do special handling for the other few places.
Building a java application that supports different Locales, but would like to customize the DateFormat display beyond what is available between FULL, LONG, MEDIUM, and SHORT DateFormat options. Would like to do things like place a character between the date and time components of a DateFormat.getDateTimeFormat(), lowercase the AM/PM, etc, at least for english.
can think of 3 ways to do it:
1) if locale is english, use my custom format string on a new SimpleDateFormat object.
2) modify the default format strings for existing locales
3) create a new locale variant that specifies the format strings I want
Can't figure out how to do 2 or 3 (or if it's even possible), and would rather not do 1... has anyone dealt with anything like this before?
also, seems like 2 or 3 would be necessary for lowercasing the AM/PM ? (Specifiying the AmPmMarkers resource for the locale's dateformat settings)
Why not use a MessageFormat instead?
Use the pattern "{0,date,short} your text here {0,time,short}" to do what you want.
Java has a Class just for this, it is the ResourceBundle Class. Back it with a properties file and you have all that you need plus more.
Even without the ResourceBundle Class you could use properties files to hold all the SimpleDateFormat formats.
Settings formats = new Settings();
Properties SDFFormats = formats.load(propertiesFile);
String SDFAmerica = SDFFormats.getProperty("FormatAmerica");
While the entry into the properties file might read
FormatAmerica = MMM-dd-yyyy
The only thing similar I've dealt with is the fact that "strftime" and "locale" say that Italian should use colons between the time fields, but Java puts full-stops between them. So I've added the following code:
// This is an incredibly ugly hack, but it's based on the fact that
// Java for some reason decided that Italy uses "." between
// hours.minutes.seconds, even though "locale" and strftime say
// something different.
hmsTimeFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM);
if (hmsTimeFormat instanceof SimpleDateFormat)
{
String str = ((SimpleDateFormat)hmsTimeFormat).toPattern();
str = str.replace('.', ':');
hmsTimeFormat = new SimpleDateFormat(str);
}
Most satisfying way to solve this that we've figured out is to load Strings am,pm,formatString from a locale-specific resource bundle, and then:
SimpleDateFormat sdf = (SimpleDateFormat)sdf.getDateTimeInstance(DateTime.SHORT,DateTime.SHORT, locale);
if (formatString != null) {
sdf = new SimpleDateFormat(formatString);
}
if (am!= null && pm != null) {
DateFormatSymbols symbols = sdf.getDateFormatSymbols();
symbols.setAmPmStrings(new String[]{am, pm});
sdf.setDateFormatSymbols(symbols);
}
Paul: not sure there's a separator in the DateFormatSymbols, though... so you probably need to keep the str.replace
I recommend using Joda Time for your date formatting. It is has powerful yet elegant flexibility in its formatting. You'll probably find that its formatters make what you want to do extremely simple.
BTW: once you go Joda you'll never go back!