Reputation: 3213
I have a simple script
<cfscript>
public string function convertTimeZone(
string toTimeZone = "America/New_York"
, date thisDate = now()
){
var azTimeZone = createObject("java", "java.util.TimeZone").getTimeZone(javaCast("string","US/Arizona"));
var azCalendar = createObject("java", "java.util.GregorianCalendar" ).init(azTimeZone);
azCalendar.set(
javaCast( "int", year( arguments.thisDate ) ),
javaCast( "int", (month( arguments.thisDate ) - 1) ),
javaCast( "int", day( arguments.thisDate ) ),
javaCast( "int", hour( arguments.thisDate ) ),
javaCast( "int", minute( arguments.thisDate ) ),
javaCast( "int", second( arguments.thisDate ) )
);
var newCal = azCalendar.clone();
newCal.setTimeInMillis(azCalendar.getTimeInMillis());
newCal.setTimeZone(javaCast("string",arguments.toTimeZone));
writeOutput('AZ Cal');
writeDump(azCalendar);
writeDump(azCalendar.Timezone);
writeDump(azCalendar.Time);
writeDump(azCalendar.getTime());
writeOutput('New Cal');
writeDump(newCal);
writeDump(newCal.Timezone);
writeDump(newCal.Time);
writeDump(newCal.getTime());
}
convertTimeZone();
</cfscript>
If you look at the output you will see that the new calendar contains the correct timezone and time but if I use getTime() it is not returning the correct value. I am sure that I have done something either in setting the time in the new calendar or maybe even the clone but I can't quite figure it out.
If I add writeDump(newCal.getTimezone());
to the list of dumps I do get "America/New_York"
Upvotes: 1
Views: 600
Reputation: 1
Actually it doesn't contain the correct time. The presentation in the dump just makes it seem that way. WriteDump()
must apply extra magic when displaying Calendar objects.
The date value does not change due to how newCal
is created. Instead of cloning azCalendar
, create a new instance and apply the azCalendar
time with set(...)
. Then the date value will change. However I'm not sure it works as expected for arbitrary time zones, only the jvm default
Supposedly Java 8+ has improved date options, which are worth investigating. For earlier versions I have used the SimpleDateFormat trick. Create two formatters. One to parse the input using the original time zone. Another to format the output, using the desired time zone. Then convert the final string back into a date object with parseDateTime().
thisDate = now();
fromTimeZone = "America/Phoenix";
toTimeZone = "America/New_York";
dateMask = "yyyy-MM-dd HH:mm:ss";
timeZone = createObject("java", "java.util.TimeZone");
fromFormat = createObject("java", "java.text.SimpleDateFormat").init(dateMask);
fromFormat.setTimeZone(timeZone.getTimeZone(fromTimeZone));
// parse input as date string
dateString = dateTimeFormat(thisDate, "yyyy-MM-dd HH:nn:ss");
fromDate = fromFormat.parse(dateString);
// format output as date string
toFormat = createObject("java", "java.text.SimpleDateFormat").init(dateMask);
toFormat.setTimeZone(timeZone.getTimeZone(toTimeZone));
// convert back into date
toDate = parseDateTime(toFormat.format(fromDate));
writeDump(toDate);
Upvotes: 0
Reputation: 7833
You can "trick" ColdFusion into using timezone adjusted date objects (since java.util.Date
cannot be timezone aware).
<cfscript>
srcDate = createDateTime(2017, 10, 07, 16, 33, 37);
srcTZ = "US/Arizona";
dstTZ = "America/New_York";
TimeZone = createObject("java", "java.util.TimeZone");
srcTZinfo = TimeZone.getTimeZone(srcTZ);
dstTZinfo = TimeZone.getTimeZone(dstTZ);
srcOffset = (srcTZinfo.getRawOffset() / 1000);
dstOffset = (dstTZinfo.getRawOffset() / 1000);
srcDSToffset = (srcTZinfo.getDSTSavings() / 1000);
dstDSToffset = (dstTZinfo.getDSTSavings() / 1000);
src2utc = dateAdd("s", -(srcOffset + srcDSToffset), srcDate);
utc2dst = dateAdd("s", (dstOffset + dstDSToffset), src2utc);
</cfscript>
<cfdump label="#srcTZ#" var="#srcDate#">
<cfdump label="#dstTZ#" var="#utc2dst#">
The snippet converts the source date object srcDate
into a UTC date using the specified timezone srcTZ
. The UTC date is then adjusted to the desired timezone dstTZ
and the final date object put into utc2dst
.
Upvotes: 1