I created a simple GWT example using eclipse, I only added a method to GreetingService which is auto-generated.
Date greetServer2() ;
It's implemented like below:
public Date greetServer2(){
// TODO Auto-generated method stub
//
String s = "2014/04/08";
DateFormat inputFormatter = new SimpleDateFormat("yyyy/MM/dd");
Date date=null;
try {
date = inputFormatter.parse(s);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return date;
}
On the client side I just show the date in a popup:
greetingService.greetServer2(new AsyncCallback<Date>() {
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
...
}
public void onSuccess(Date result) {
Window.alert(result.toString());
}
});
I run it via eclipse, the url generated by eclipse is:
http://127.0.0.1:8888/HelloGWT.html?gwt.codesvr=127.0.0.1:9997
The popup window says "Tue Apr 08 00:00:00 CLST 2014"
But if I access without gwt.codesvr parameter:
http://127.0.0.1:8888/HelloGWT.html
The popup window says "Mon Apr 07 23:00:00 GMT-400 2014"
My GWT is 2.5.1, my JDK is 1.7.0_25.
Any clues?
Thanks in advance.
One result comes from a Java code, and the other one is produced by your browser. The difference is in the time zones. If you want consistent results, you should not use date.toString(), but display date using a DateFormat, and pass a time zone to it.
Remember that your users may be in different time zones, and they will all see a different "time" (and even a different date, like in your example) based on their browser settings, unless you specify a time zone in your code.
UPDATE:
There are different strategies for dealing with time zones. For example, you can save all dates as Long values (date.getTime()) for consistency. Then, you display it using a DateFormat and a time zone.
If you want to make sure that your date starts exactly at midnight in your selected time zone, make an adjustment before saving or using it. This is how I do it:
public static Long toMidnight(Long date, TimeZone timeZone) {
return date - date % (24 * 60 * 60 * 1000) +
timeZone.getOffset(new Date(date)) * 60 * 1000;
}
Related
i have a really simple problem, i don't know how to deduct the user's date by 01/01 / (the user year) +1. Im really stuck at this point.
public static void main(String[] args)
{
String date;
Scanner teclado = new Scanner (System.in);
System.out.println("Dame una fecha formato dd/mm/yyyy");
date=teclado.next();
Date mydate =FinalAnio.ParseFecha(date);
System.out.println(mydate);
}
public static Date ParseFecha(String fecha)
{
SimpleDateFormat formato = new SimpleDateFormat("dd/mm/yyyy");
Date fechaDate = null;
try
{
fechaDate = formato.parse(fecha);
}
catch (ParseException ex)
{
System.out.println(ex);
}
return fechaDate;
}
The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Do not use mm for the month as it is used for the minute. For the month, the correct symbol is MM. Check DateTimeFormatter to learn more about various symbols used for parsing/formatting string/date-time.
Learn about the calculations of the period and duration from Period and Duration tutorial from Oracle. It would also be worth going through this Wikipedia page on Durations.
Demo:
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Locale;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter date in the format dd/MM/yyyy: ");
String strDate = scanner.next();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/uuuu", Locale.ENGLISH);
LocalDate userDate = LocalDate.parse(strDate, dtf);
// The date representing 01/01/(the user year)+1
LocalDate targetDate = userDate.withDayOfMonth(1).withMonth(1).plusYears(1);
System.out.println("User's date: " + strDate);
System.out.println("Target date: " + targetDate.format(dtf));
Period period = Period.between(userDate, targetDate);
System.out.printf("Difference: %d days %d months %d years%n", period.getDays(), period.getMonths(),
period.getYears());
System.out.println("The difference in terms of days: " + ChronoUnit.DAYS.between(userDate, targetDate));
}
}
A sample run:
Enter date in the format dd/MM/yyyy: 20/10/2015
User's date: 20/10/2015
Target date: 01/01/2016
Difference: 12 days 2 months 0 years
The difference in terms of days: 73
Learn about the modern date-time API from Trail: Date Time.
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work.
DateTimeFormatter formatador = DateTimeFormatter.ofPattern("dd/MM/uuuu");
String entradaUsuario = "02/12/2020";
LocalDate fecha = LocalDate.parse(entradaUsuario, formatador);
LocalDate finDeAño = fecha.with(MonthDay.of(Month.DECEMBER, 31));
long diasRestantes = ChronoUnit.DAYS.between(fecha, finDeAño);
System.out.println(diasRestantes);
Output is:
29
In the format pattern string upper case MM is for month of year (lower case mm would be minute of hour, so not useful here). uuuu is for year (yyyy would work too).
fecha.with(MonthDay.of(Month.DECEMBER, 31)) adjusts the date to December 31 in the same year.
Link
Oracle tutorial: Date Time explaining how to use java.time.
In my flutter application I get appointment time in UTC format from a server.
I would like to display it in local time.
Is there a way to convert UTC to local time in flutter?
Dart has inbuilt DateTime type that provides quite a few handy methods to convert between time formats.
void main() {
var utc = DateTime.parse("2020-06-11 17:47:35 Z");
print(utc.toString()); // 2020-06-11 17:47:35.000Z
print(utc.isUtc.toString()); // true
print(utc.toLocal().toString()); //2020-06-11 23:17:35.000
}
I have the following code which uses all recommendations discussed in similar questions.
public class DateUtils {
static String secondsToDate(String seconds) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(Long.parseLong(seconds) * 1000);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
return String.format("%d-%d-%d", year, month, day);
}
static String dateToSeconds(String date) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
Date parsed = format.parse(date);
long timeInMillis = parsed.getTime();
return Long.toString(timeInMillis / 1000);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String timestamp = "1409515200";
String date = secondsToDate(timestamp);
String timestamp2 = dateToSeconds(date);
System.out.printf("%s %s", timestamp, timestamp2);
}
}
The result of the code:
1409515200 1406836800
As you can see the conversion back and forth doesn't work. What's wrong?
Your problem here is the rounding. In the first method, you are converting your timestamp (which is the number of milliseconds from 1970) into a date. You are now getting only the date, discarding hours, minutes, seconds and milliseconds and converting it back. This means that you will always have a difference of the amount you are discarding (between 0 at 00:00:00:000 and 86400000 at 23:59:59:999). To fix it, simply change your date format to include the hours with milliseconds precision.
The answer by Aurasphere is correct and should be accepted.
Some further tips…
Use date-time classes for date-time values, rather than strings. Perform your business logic using date-time objects, and pass around such objects amongst your code rather than strings.
Avoid tracking date-times as a count-from-epoch. When you do need to serialize to text, use the unambiguous and easy-to-read formats defined by the ISO 8601 standard such as 2016-05-09T16:47:54Z.
You are using old troublesome legacy classes that have been supplanted by the java.time framework built into Java 8 and later. Much of that functionality has been back-ported to Java 6 & 7 in the ThreeTen-Backport project, and further adapted for Android in the ThreeTenABP project.
Using java.time classes will make your work easier and your code easier to comprehend, less likely to encounter the confusion seen in the Question.
An Instant is a moment on the timeline in UTC, with a resolution of nanoseconds. That class offers a convenient factory method ofEpochSecond, so no need to multiply by a thousand for milliseconds.
String input = "1409515200";
long seconds = Long.parseLong( input );
Instant instant = Instant.ofEpochSecond( seconds );
To get the wall-clock time for some locality, assign a time zone to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
To generate a string in standard ISO 8601 format, call toString. Note that this method extends that format to append the name of the time zone in square brackets. For example, 2007-12-03T10:15:30+01:00[Europe/Paris].
String output = zdt.toString();
To get the date-only as in the Question, extract a LocalDate object.
LocalDate localDate = zdt.toLocalDate();
From there you can determine the first moment of the day. The first moment is not always the time-of-day 00:00:00.0, so let java.time determine that.
ZonedDateTime zdtStartOfDay = localDate.atStartOfDay( zoneId );
To get the two long integer counts of seconds seen in the Question, extract an Instant from each of our ZonedDateTime objects, and ask for the seconds-since-epoch. Note that you might be losing data as the ZonedDateTime/Instant objects can store values with a resolution up to nanoseconds. The call asking for whole seconds from epoch means any fraction of a second is truncated.
long seconds1 = zdt.toInstant().getEpochSecond();
long seconds2 = zdtStartOfDay.toInstant().getEpochSecond();
i try to get the current time like that :
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
String sendingDateAndTime = dateFormat.format(cal.getTime()).trim();
but i get the GMT time when i want the system time (and not the local time because my software will be executed in several countries so i can use the TimeZone object).
I need to use the date library and the GregorianCalendar library but i get the same wrong result.
Many people have the same problem but all the solution that i saw it's to put hard code like "Europe" or something else in the timezone object.
If someone can help you.
Thankssss
---------------------------- UPDATE ------------------------------------
I tried to use the System.currentTimeMillis() and to give it as parameter to calendar object, but i get the GMT time too
How about this for the GMT time?
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
And this for the local computer time?
Calendar calendar = Calendar.getInstance();
DateFormat will default to the local time zone. The internal format of a Calendar object is the number of milliseconds past midnight, January 1, 1970, GMT.
Edited to add: When I run this code, I get my local time.
public static void main (String[] args) {
Calendar calendar = Calendar.getInstance();
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z");
String sendingDateAndTime = dateFormat.format(calendar.getTime());
System.out.println(sendingDateAndTime);
}
When I run this code, I get GMT, although the time zone is still my local time zone.
public static void main (String[] args) {
Calendar calendar = Calendar.getInstance();
TimeZone timeZone = calendar.getTimeZone();
int offsetFromUTC = timeZone.getOffset(calendar.getTimeInMillis());
calendar.add(Calendar.MILLISECOND, -offsetFromUTC);
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z");
String sendingDateAndTime = dateFormat.format(calendar.getTime());
System.out.println(sendingDateAndTime);
}
I've noticed that if a date property comes back from the server with the value "2013-07-11T17:11:04.700", then breeze changes the value to Thu Jul 11 19:11:04 UTC+0200 2013.
Notice the time is now 2 hours ahead !
I had already come across this issue when saving entities, so I had to explicitly convert my date properties using momentjs :
date.hours(date.hours() - moment().zone() / 60);
But now it seems the problem occurs also when doing read operations.
What's the best way to make sure breeze does not alter values of my date properties ?
Breeze does not manipulate the datetimes going to and from the server in any way EXCEPT to add a UTZ timezone specifier to any dates returned from the server that do not already have one. This is only done because different browsers interpret dates without a timezone specifier differently and we want consistency between browsers.
The source of your issues is likely to be that when you save your data with dates to the database, that the dateTime datatype you are using does NOT contain a timezone offset. This means that when the data is retrieved you are likely "losing" the offset and the Breeze default mentioned above kicks in. This can be corrected by using a database date time datatype with an timezone offset ( datetime2 or datetimeoffset in SQLServer).
Note that your browser DOES format dates according to it's current timezone.
Another approach is that you can replace Breeze's DataType.parseDateFromServer to NOT infer any time zone info if it is not provided:
breeze.DataType.parseDateFromServer = function (source) {
return new Date(Date.parse(source));
};
However, this can run into the problem that different browsers interpret DateTime strings without a time zone offset differently... So you may still get strange results depending on the browser. If that happens you will need to add some browser detection code to the snippet above.
Another alternative is to do the following using the moment.js library.
breeze.DataType.parseDateFromServer = function (source) {
var date = moment(source);
return date.toDate();
};
Not sure how helpful this is, but hopefully Breeze's behavior is clearer.
By default, Breeze does not provide any way to do this, but you can keep the below code in your model JS file to overcome this issue:
breeze.DataType.parseDateFromServer = function (source) {
if (typeof source === 'string') {
//Check for local offset time or UTC time from server
if (source.slice(-1) !== "Z") {
var oldSource = source;
try {
source = source.substring(0, source.lastIndexOf("-") - 1)
source = new Date(source);
var tzDifference = source.getTimezoneOffset();
//convert the offset to milliseconds, add to targetTime, and make a new Date
var offsetTime = new Date(source.getTime() + tzDifference * 60 * 1000);
return offsetTime;
}
catch (err) {
source = new Date(source);
return source;
}
}
else {
source = new Date(source);
var tzDifference = source.getTimezoneOffset();
//convert the offset to milliseconds, add to targetTime, and make a new Date
var offsetTime = new Date(source.getTime() + tzDifference * 60 * 1000);
return offsetTime;
}
}
}