I'm currently a developing a sync module for one of my applications. I'm syncing the records between local and server based on LastUpdated time, which is nothing but a timestamp. The server is of Singapore, so how can I set the timezone to Singapore in my Android application?
I have tried,
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("VST") );
and,
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("Asia/Singapore"));
System.out.println(calendar.get(Calendar.HOUR_OF_DAY));
Still no luck.
Or is there any way I can set the common timezone for both local and server? Server side language is ASP.Net
Your SimpleDateFormat example is almost correct. I believe you want SGT for Singapore and you need to call DateFormat.format(Date). You might also pass the TimeZone to Calendar.getInstace(TimeZone) like
TimeZone tz = TimeZone.getTimeZone("SGT");
sdf.setTimeZone(tz);
System.out.println(sdf.format(Calendar.getInstance().getTime()));
System.out.println(Calendar.getInstance(tz));
Joda-Time
When doing anything significant with date-time work, you should avoid the java.util.Date and java.util.Calendar classes as they are notoriously troublesome, confusing, and flawed. Instead use the Joda-Time library which does work in Android.
ISO 8601
Your string input is close to standard ISO 8601 format. Just replace the SPACE with a T. Then pass the result to the constructor of DateTime along with a DateTimeZone object representing the intended time zone of that string. Search StackOveflow for hundreds of examples.
UTC
As Elliott Frisch commented, on the server-side you should be working and storing date-time values all in UTC. Convert to local zoned values only when expected by the user in the user interface.
The server itself should be set to UTC, or if not possible then set to Reykjavík Iceland. But your programming should never assume the server is so set. Your programming should always specify the desired time zone.
Search StackOverflow for hundreds of examples and discussion of these points.
Finally, this is how I solved it.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
TimeZone tz = TimeZone.getTimeZone("Asia/Singapore");
sdf.setTimeZone(tz);
java.util.Date date= new java.util.Date();
Timestamp local = new Timestamp(date.getTime());
String strDate = sdf.format(date);
System.out.println("Local in String format " + strDate);
Related
On the server code I would like to get the "Day" but not of server date/time but of a specific timezone, GMT+8 specifically.
I have this code:
DateFormat formatter = new SimpleDateFormat("EEEE", Locale.ENGLISH);
String day = formatter.format(new Date()).toUpperCase();
availabilities.add(Availability.builder()
.day(day)
.from(LocalTime.now())
.to(LocalTime.now())
.build());
How do I get the "day" for the specific timezone and also have to build a LocalTime.now() which will return a LocalTime object but not the current time of the said timezone.
For instance as of this writing GMT+8 now is ~6:25 am so that would be the one that LocalTime.now() returns instead of the cloud server which is in the different timezone.
SDF and new Date() are old API and you don't want these. For example, Date is a lie; it does not represent a date whatsoever, it actually represents an instant in time. This is dumb - that's why there is a new API.
EDIT: Made it simpler by invoking the now method of ZonedDateTime.
private static final ZoneId TARGET_ZONE = ZoneId.of("Singapore");
ZonedDateTime atTarget = ZonedDateTime.now(TARGET_ZONE);
DayOfWeek whatYouWant = atTarget.getDayOfWeek();
NB: You can go with +8 explicitly, then you're looking for an OffsetDateTime, and atOffset(ZoneOffset.ofHours(8)), but that's... weird. Who could possibly want 'UTC+8'? Nobody, except airplanes and military operations in a certain zone, and surely that's not your target audience.
I have time 12:00:00 in format HH:mm:ss.
I know that this time comes from server witch is setup with +3 offset.
If i use SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");, it parses time with regard to device, which can be in a different timezone.
Is there another way to parse it with regard to +3 offset except adding it to the original string?
First, should your server rather send the time in UTC? If clients are everywhere, this would seem more time zone neutral and standardized. However, the way to handle it in code wouldn’t be much different. In any case the server offset form UTC could be constant:
private static final ZoneOffset serverOffset = ZoneOffset.ofHours(3);
In real code you will probably want to make it configurable somehow, though. To parse:
OffsetTime serverTime = LocalTime.parse("12:00:00").atOffset(serverOffset);
System.out.println(serverTime);
This prints
12:00+03:00
Since your time format agrees with LocalTime’s default (ISO 8601), we need no explicit formatter. If a representation of the time with offset is all you need, we’re done. If you need to convert to the user’s local time, to do that reliably you need to decide both a time zone and a date:
LocalTime clientTime = serverTime.atDate(LocalDate.of(2018, Month.JANUARY, 25))
.atZoneSameInstant(ZoneId.of("Indian/Maldives"))
.toLocalTime();
System.out.println(clientTime);
With the chosen day and zone we get
14:00
Please substitute your desired time zone and date.
Just hypothetically, if you knew the user’s offset from UTC, you could use just that:
LocalTime clientTime = serverTime.withOffsetSameInstant(ZoneOffset.of("-08:45"))
.toLocalTime();
The example yields 00:15. However, no one knows when the politicians introduce summer time (DST) or other anomalies in the user’s time zone, so I discourage relying on an offset alone.
And yes, I too am using java.time. SimpleDateFormat is not only long outdated, it is also notoriously troublesome, so java.time is what I warmly recommend.
Set the timezone on your SimpleDateFormat object:
SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss");
fmt.setTimeZone(TimeZone.getTimeZone("GMT+03:00"));
I recommend you use the Java 8 date and time API (package java.time) instead of the old API, of which SimpleDateFormat is a part.
Using the Java 8 DateTime API:
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("HH:mm:ss");
LocalTime clientLocalTime = LocalTime
.parse("12:00:00", formatter)
// Create an OffsetTime object set to the server's +3 offset zone
.atOffset(ZoneOffset.ofHours(3))
// Convert the time from the server timezone to the client's local timezone.
// This expects the time value to be from the same day,
// otherwise the local timezone offset may be incorrect.
.withOffsetSameInstant(ZoneId.systemDefault().getRules().getOffset(Instant.now()))
// Drop the timezone info - not necessary
.toLocalTime();
I'm using Java 6. Our servers are on Eastern Standard Time (GMT-5), and I'm trying to store a value that should be interpreted as such but I'm confused about how to convert it. I have
String dateStr = "1368921600000"; // This is 5/19/2013 00:00:00
final Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("GMT-5"));
cal.setTimeInMillis(Long.parseLong(dateStr));
final java.util.Date dateObj = cal.getTime();
System.out.println(dateObj.toString());
but right now this prints out "Sat May 18 19:00:00 CDT 2013" (since my local machine is on CDT) but I want the result to be "Sat May 18 24:00:00 CDT 2013". How can i interpret the date string "1368921600000" as an EST date? Thanks, - Dave
1368921600000 is an instant in time, the same instant, everywhere in the world. To convert this to a date and time, you have to specify where in the world you want to know the date/time at that instant. It just so happens that the timestamp is relative to UTC, and is Sun, 19 May 2013 00:00:00 GMT.
If you want the time of this instant (the same instant) somewhere else in the world, you can use the Calendar as you did and extract the individual field values (e.g. HOUR_OF_DAY). If all you care about is getting a text string, you use a DateFormat instance such as SimpleDateFormat:
DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");
df.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String timeOnUSEastCoast = df.format(new Date(1368921600000L));
// will be GMT-5 or GMT-4 depending on DST
In this example, the output would be GMT-4: Sat, 18 May 2013 20:00:00 EDT (not only has the hour changed, but it's still the previous day on the US east coast).
If you want to output the UTC time but just want to pretend it's EST then it's just easier to tell the DateFormat to leave off the time zone field (remove the "z") in the text output and call it whatever you want, but understand that the timestamp value is always UTC.
It is often not necessary to use the Joda Time library to get historically accurate time-zone- and daylight-savings-aware local time mappings, although this is the common go to response for many.
If you have a database of timestamps that require local time conversion, then here are some principles that have served me well:
Store date/times (Instants, in the parlance of Joda; Dates, in the parlance of the Java Calendar API) in UTC time. UTC does not care about DST. It does not care about time zones. UTC simply represents a universally representable moment in time. This step alone can save a lot of date/time headaches.
Database records should contain TimeZone and/or Locale fields so that mapping from UTC can be performed. Think about your data. Every timestamp in your database does not need time zone information associated with it. Instead, associate the time zone data with a part of your data model that provides appropriate granularity. If your app will only ever be localized in one time zone, then you needn't store this infor at all. In my recent project, I created a Locale table that contains the TZ ID for timestamps in my Encounters table. All other timestamps are subordinate to these records, so it made sense to associate it there.
Use the Java API GregorianCalendar to map UTC Dates to local time. And that's all I ever use it for. I almost never use GregorianCalendars to do date arithmetic or other date operations. Here is the paradigm that I've been working with:
public static void main(String[] args) {
m_GregorianCalendar = new GregorianCalendar(TimeZone.getTimeZone(
"America/Chicago"));
Date d = new Date();
String fmt = "dd-MMM-yyyy # HH:mm";
:
:
String myDate = mapToLocalTime(d, fmt, gc);
:
:
}
public String mapToLocalTime(Date utc, String format, GregorianCalendar gc) {
gc.setTime(utc); // this calendar is already timezone aware (constructed
// with time zone id (DST too))
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.setCalendar(gc); // formatter uses conventions of calendar
sdf.applyPattern(fmt); // pattern for formatter
return sdf.format(utc);
}
Consider representing timestamps internally in a numeric format (longs, doubles). This greatly simplifies date comparisons and date arithmetic. The only downside is that conversions must be done to format the data into a human recognizable form, but if you use functions for these conversions it need not be a big deal at all.
Use either a new java.util.SimpleDateFormat(format) or java.util.DateFormat.getDateTimeInstance(int,int), then use #setTimeZone(timezone).
When you're printing Date.toString(), the Calendar's time zone is not taken into consideration at all. After you do a cal.getTime(), whatever was set in Calendar is no longer relevant.
What is is TimeZone's default time zone.
So right before printing the date, set the default time zone to the one you want to print in, e.g.:
String dateStr = "1368921600000"; // This is 5/19/2013 00:00:00
final Calendar cal = Calendar.getInstance();
TimeZone gmtZero = TimeZone.getTimeZone("GMT");
cal.setTimeInMillis(Long.parseLong(dateStr));
final java.util.Date dateObj = cal.getTime();
TimeZone.setDefault(gmtZero);
System.out.println(dateObj.toString());
This will print the date in GMT regardless of your system time zone.
Just remember to bring back the original default TimeZone afterwards!
I try to get the date of yesterday. So I write the next function:
public String getYestrday() {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
return dateFormat.format(date.getDate() - 1);
}
But it gives me the next warning:
The method getDate() from the type Date is deprecated
and it doesn't do it work.
Thank you for your help.
Date#getDate() is a deprecated method after JDK 1.1. You should be using Calendar class instead to manipulate dates.
From API:
Prior to JDK 1.1, the class Date had two additional functions. It
allowed the interpretation of dates as year, month, day, hour, minute,
and second values. It also allowed the formatting and parsing of date
strings. Unfortunately, the API for these functions was not amenable
to internationalization. As of JDK 1.1, the Calendar class should be
used to convert between dates and time fields and the DateFormat class
should be used to format and parse date strings. The corresponding
methods in Date are deprecated.
It is also clearly documented in the API using Date#getDate() to use Calendar#get(Calendar.DATE);
Deprecated. As of JDK version 1.1, replaced by
Calendar.get(Calendar.DAY_OF_MONTH)
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
return dateFormat.format(cal.getTime());
Use java.util.Calendar to do it. Or try JODA.
you can use Calendar class to do the same task:
Calendar c = new Calendar();
//c.add(Calendar.DAY_OF_MONTH, -1);
Date d = c.getTime();
Avoid java.util.Date & .Calendar
The accepted answer is correct. However, the java.util.Date and .Calendar classes are notoriously troublesome. Avoid them. Use either Joda-Time or the new java.time package (in Java 8).
Separate Date-Time Manipulation From Formatting
Also, the code in the question mixes date-time work with formatting. Separate those tasks to make your code clear and testing/debugging easier.
Time Zone
Time zone is critical in date-time work. If you ignore the issue, the JVM's default time zone will be applied. A better practice is to always specify rather than rely on default. Even when you want the default, explicitly call getDefault.
The beginning of the day is defined by the time zone. A new day dawns earlier in Paris than in Montréal. So if by "yesterday" you mean the first moment of that day, then you should (a) specify a time zone, and (b) call withTimeAtStartOfDay.
Joda-Time
Example code in Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime today = DateTime.now( timeZone );
Or convert from a java.util.Date object.
DateTime today = new DateTime( myJUDate, timeZone );
Subtract a day to get to yesterday (or day before).
DateTime yesterday = today.minusDays( 1 );
DateTime yesterdayStartOfDay = today.minusDays( 1 ).withTimeAtStartOfDay();
By default, Joda-Time and java.time parse/generate strings in ISO 8601 format.
String output = yesterdayStartOfDay.toString(); // Uses ISO 8601 format by default.
Use a formatter for a full date as four digit year, two digit month of year, and two digit day of month (yyyy-MM-dd). Such a formatter is already defined in Joda-Time.
String outputDatePortion = ISODateFormat.date().print( yesterdayStartOfDay );
Following works for me
int date = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
I need to convert JsDate to java.util.Date. I searched but I couldn't find anything. So could you help me with this problem?
Edit: I do this conversion process on GWT screen. I have Datepicker on screen and it gives me JsDate value when I use it's getValue() method. So I'm supposed to put this value into the property of an object which has Date type.
ObjectName.setDate(PickerName.getValue());
I hope my edit will be more clear.
Edit2:
This line is the solution of my problem:
myObject.setDate(new Date((long) myPicker.getValue().getTime()));
The best way of dates conversion is using time in milliseconds, UTC. Both JS Date object and java.util.Date class support conversion to milliseconds (getTime()) and instantiating from milliseconds (using constructor).
You can create a java.util.Date object from the 'time since epoch' value of the JS Date
javascript
var d = new Date().getTime();
java
// get value from client (ajax, form, etc), and construct in Date object
long valueFromClient = ...
Date date = new Date(valueFromClient);
String formatted = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
If people like me are forced to parse a JS-formatted date string (as the result of (new Date()).toString() in JavaScript), here is the SimpleDateFormat spec I used:
DateFormat jsfmt = new SimpleDateFormat("EE MMM d y H:m:s 'GMT'Z (zz)");
If you have control of the producer of the dates, I concur that using timestamps or at least .toUTCString() is definitely more robust.
You may want this:
java:
String jsDate="2013-3-22 10:13:00";
Date javaDate=new SimpleDateFormat("yy-MM-dd HH:mm:ss").parse(jsDate);
System.out.println(javaDate);
ISO 8601 and java.time
ISO 8601 is the international standard for date and time including date and time formats. About any programming language has support for it, including both JavaScript and Java.
In JavaScript produce a string in ISO 8601 format using Date.toISOString(). We don’t need any formatter.
var d = new Date();
var n = d.toISOString();
console.log(n);
The result is somewhat human readable as long as you remember that it’s in UTC, denoted by the trailing Z.
In Java parse the string using Instant.parse(). We don’t need to specify any formatter here either.
String stringFromJavaScript = "2021-07-12T05:54:03.365Z";
Instant inst = Instant.parse(stringFromJavaScript);
System.out.println(inst);
Output:
2021-07-12T05:54:03.365Z
The question asked for a java.util.Date for the result from a date picker. We should avoid using java.util.Date for this both because despite the name a Date does not represent a date and because the Date class is poorly designed and long outdated. For a date without time of day a LocalDate is appropriate:
LocalDate date = inst.atZone(ZoneId.systemDefault()).toLocalDate();
System.out.println(date);
In my time zone the output was:
2021-07-12
The conversion is time zone dependent and will only be correct if the default time zone of the JVM (or which time zone you pass to atZone()) is the same as used by the date picker.
If you do need a Date for a legacy API not yet upgraded to java.time:
Date oldfashionedDate = Date.from(inst);
System.out.println(oldfashionedDate);
Mon Jul 12 07:54:03 CEST 2021
Links
Wikipedia article: ISO 8601
Oracle tutorial: Date Time explaining how to use java.time.
I would suggest using the DateFormat parse method (doc can be found here). It can parse a string representation of a date and return a java.util.Date.
JS Date --
new Date()
Wed Aug 14 2019 14:54:38 GMT+0530 (India Standard Time)
Java Date --
new Date().toISOString()
"2019-08-14T09:25:50.136Z"