Ticket #17576: 17576-timezones-V2.diff
| File 17576-timezones-V2.diff, 12.9 KB (added by , 7 years ago) |
|---|
-
src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
36 36 import java.util.Hashtable; 37 37 import java.util.List; 38 38 import java.util.Objects; 39 import java.util.Optional;40 39 import java.util.TimeZone; 41 40 import java.util.concurrent.TimeUnit; 42 41 … … 540 539 * 541 540 */ 542 541 private class SetOffsetActionListener implements ActionListener { 542 JCheckBox ckDst; 543 ImageDisplay imgDisp; 544 JLabel lbExifTime; 545 JosmTextField tfGpsTime; 543 546 547 class TimeZoneItem implements Comparable<TimeZoneItem> { 548 private TimeZone tz; 549 private String rawString; 550 private String dstString; 551 552 public TimeZoneItem(TimeZone tz) { 553 this.tz = tz; 554 } 555 556 public String getFormattedString() { 557 if (ckDst.isSelected()) { 558 return getDstString(); 559 } else { 560 return getRawString(); 561 } 562 } 563 564 public String getDstString() { 565 if (dstString == null) { 566 dstString = formatTimezone(tz.getRawOffset() + tz.getDSTSavings()); 567 } 568 return dstString; 569 } 570 571 public String getRawString() { 572 if (rawString == null) { 573 rawString = formatTimezone(tz.getRawOffset()); 574 } 575 return rawString; 576 } 577 578 public String getID() { 579 return tz.getID(); 580 } 581 582 @Override 583 public String toString() { 584 return getID() + " (" + getFormattedString() + ")"; 585 } 586 587 @Override 588 public int compareTo(TimeZoneItem o) { 589 return getID().compareTo(o.getID()); 590 } 591 592 private String formatTimezone(int offset) { 593 return new GpxTimezone((double) offset / TimeUnit.HOURS.toMillis(1)).formatTimezone(); 594 } 595 } 596 544 597 @Override 545 598 public void actionPerformed(ActionEvent arg0) { 546 599 SimpleDateFormat dateFormat = (SimpleDateFormat) DateUtils.getDateTimeFormat(DateFormat.SHORT, DateFormat.MEDIUM); … … 551 604 + "And then, simply capture the time you read on the photo and select a timezone<hr></html>")), 552 605 BorderLayout.NORTH); 553 606 554 ImageDisplayimgDisp = new ImageDisplay();607 imgDisp = new ImageDisplay(); 555 608 imgDisp.setPreferredSize(new Dimension(300, 225)); 556 609 panel.add(imgDisp, BorderLayout.CENTER); 557 610 … … 565 618 gc.anchor = GridBagConstraints.WEST; 566 619 panelTf.add(new JLabel(tr("Photo time (from exif):")), gc); 567 620 568 JLabellbExifTime = new JLabel();621 lbExifTime = new JLabel(); 569 622 gc.gridx = 1; 570 623 gc.weightx = 1.0; 571 624 gc.fill = GridBagConstraints.HORIZONTAL; … … 580 633 gc.anchor = GridBagConstraints.WEST; 581 634 panelTf.add(new JLabel(tr("Gps time (read from the above photo): ")), gc); 582 635 583 JosmTextFieldtfGpsTime = new JosmTextField(12);636 tfGpsTime = new JosmTextField(12); 584 637 tfGpsTime.setEnabled(false); 585 638 tfGpsTime.setMinimumSize(new Dimension(155, tfGpsTime.getMinimumSize().height)); 586 639 gc.gridx = 1; … … 598 651 gc.weightx = gc.weighty = 0.0; 599 652 gc.fill = GridBagConstraints.NONE; 600 653 gc.anchor = GridBagConstraints.WEST; 601 panelTf.add(new JLabel(tr(" I amin the timezone of: ")), gc);654 panelTf.add(new JLabel(tr("Photo taken in the timezone of: ")), gc); 602 655 656 ckDst = new JCheckBox(tr("Use daylight saving time (where applicable)"), Config.getPref().getBoolean("geoimage.timezoneid.dst")); 657 603 658 String[] tmp = TimeZone.getAvailableIDs(); 604 List< String> vtTimezones = new ArrayList<>(tmp.length);659 List<TimeZoneItem> vtTimezones = new ArrayList<>(tmp.length); 605 660 661 String defTzStr = Config.getPref().get("geoimage.timezoneid", ""); 662 if (defTzStr.isEmpty()) { 663 defTzStr = TimeZone.getDefault().getID(); 664 } 665 TimeZoneItem defTzItem = null; 666 606 667 for (String tzStr : tmp) { 607 TimeZone tz = TimeZone.getTimeZone(tzStr); 608 609 String tzDesc = tzStr + " (" + 610 new GpxTimezone(((double) tz.getRawOffset()) / TimeUnit.HOURS.toMillis(1)).formatTimezone() + 611 ')'; 612 vtTimezones.add(tzDesc); 668 TimeZoneItem tz = new TimeZoneItem(TimeZone.getTimeZone(tzStr)); 669 vtTimezones.add(tz); 670 if (defTzStr.equals(tzStr)) { 671 defTzItem = tz; 672 } 613 673 } 614 674 615 675 Collections.sort(vtTimezones); 616 676 617 JosmComboBox< String> cbTimezones = new JosmComboBox<>(vtTimezones.toArray(new String[0]));677 JosmComboBox<TimeZoneItem> cbTimezones = new JosmComboBox<>(vtTimezones.toArray(new TimeZoneItem[0])); 618 678 619 String tzId = Config.getPref().get("geoimage.timezoneid", ""); 620 TimeZone defaultTz; 621 if (tzId.isEmpty()) { 622 defaultTz = TimeZone.getDefault(); 623 } else { 624 defaultTz = TimeZone.getTimeZone(tzId); 679 if (defTzItem != null) { 680 cbTimezones.setSelectedItem(defTzItem); 625 681 } 626 682 627 cbTimezones.setSelectedItem(defaultTz.getID() + " (" +628 new GpxTimezone(((double) defaultTz.getRawOffset()) / TimeUnit.HOURS.toMillis(1)).formatTimezone() +629 ')');630 631 683 gc.gridx = 1; 632 684 gc.weightx = 1.0; 633 685 gc.gridwidth = 2; … … 634 686 gc.fill = GridBagConstraints.HORIZONTAL; 635 687 panelTf.add(cbTimezones, gc); 636 688 689 gc.gridy = 3; 690 panelTf.add(ckDst, gc); 691 692 ckDst.addActionListener(l -> { 693 cbTimezones.repaint(); 694 }); 695 637 696 panel.add(panelTf, BorderLayout.SOUTH); 638 697 639 698 JPanel panelLst = new JPanel(new BorderLayout()); … … 653 712 imgList.getSelectionModel().addListSelectionListener(evt -> { 654 713 int index = imgList.getSelectedIndex(); 655 714 ImageEntry img = yLayer.getImageData().getImages().get(index); 656 imgDisp.setImage(img); 657 Date date = img.getExifTime(); 658 if (date != null) { 659 DateFormat df = DateUtils.getDateTimeFormat(DateFormat.SHORT, DateFormat.MEDIUM); 660 lbExifTime.setText(df.format(date)); 661 tfGpsTime.setText(df.format(date)); 662 tfGpsTime.setCaretPosition(tfGpsTime.getText().length()); 663 tfGpsTime.setEnabled(true); 664 tfGpsTime.requestFocus(); 665 } else { 666 lbExifTime.setText(tr("No date")); 667 tfGpsTime.setText(""); 668 tfGpsTime.setEnabled(false); 669 } 715 updateExifComponents(img); 670 716 }); 671 717 panelLst.add(new JScrollPane(imgList), BorderLayout.CENTER); 672 718 … … 678 724 return; 679 725 ImageEntry entry = new ImageEntry(fc.getSelectedFile()); 680 726 entry.extractExif(); 681 imgDisp.setImage(entry); 682 683 Date date = entry.getExifTime(); 684 if (date != null) { 685 lbExifTime.setText(DateUtils.getDateTimeFormat(DateFormat.SHORT, DateFormat.MEDIUM).format(date)); 686 tfGpsTime.setText(DateUtils.getDateFormat(DateFormat.SHORT).format(date)+' '); 687 tfGpsTime.setEnabled(true); 688 } else { 689 lbExifTime.setText(tr("No date")); 690 tfGpsTime.setText(""); 691 tfGpsTime.setEnabled(false); 692 } 727 updateExifComponents(entry); 693 728 }); 694 729 panelLst.add(openButton, BorderLayout.PAGE_END); 695 730 … … 718 753 continue; 719 754 } 720 755 721 String selectedTz = (String) cbTimezones.getSelectedItem(); 722 int pos = selectedTz.lastIndexOf('('); 723 tzId = selectedTz.substring(0, pos - 1); 724 String tzValue = selectedTz.substring(pos + 1, selectedTz.length() - 1); 756 TimeZoneItem selectedTz = (TimeZoneItem) cbTimezones.getSelectedItem(); 725 757 726 Config.getPref().put("geoimage.timezoneid", tzId); 758 Config.getPref().put("geoimage.timezoneid", selectedTz.getID()); 759 Config.getPref().putBoolean("geoimage.timezoneid.dst", ckDst.isSelected()); 727 760 tfOffset.setText(GpxTimeOffset.milliseconds(delta).formatOffset()); 728 tfTimezone.setText( tzValue);761 tfTimezone.setText(selectedTz.getFormattedString()); 729 762 730 763 isOk = true; 731 764 … … 733 766 statusBarUpdater.updateStatusBar(); 734 767 yLayer.updateBufferAndRepaint(); 735 768 } 769 770 void updateExifComponents(ImageEntry img) { 771 imgDisp.setImage(img); 772 Date date = img.getExifTime(); 773 if (date != null) { 774 DateFormat df = DateUtils.getDateTimeFormat(DateFormat.SHORT, DateFormat.MEDIUM); 775 df.setTimeZone(DateUtils.UTC); //EXIF data does not contain timezone information and is read as UTC 776 lbExifTime.setText(df.format(date)); 777 tfGpsTime.setText(df.format(date)); 778 tfGpsTime.setCaretPosition(tfGpsTime.getText().length()); 779 tfGpsTime.setEnabled(true); 780 tfGpsTime.requestFocus(); 781 } else { 782 lbExifTime.setText(tr("No date")); 783 tfGpsTime.setText(""); 784 tfGpsTime.setEnabled(false); 785 } 786 } 736 787 } 737 788 738 789 private class GpxLayerAddedListener implements LayerChangeListener { … … 817 868 JPanel panelTf = new JPanel(new GridBagLayout()); 818 869 819 870 try { 820 timezone = GpxTimezone.parseTimezone(Optional.ofNullable(Config.getPref().get("geoimage.timezone", "0:00")).orElse("0:00")); 871 String tz = Config.getPref().get("geoimage.timezone"); 872 if (!tz.isEmpty()) { 873 timezone = GpxTimezone.parseTimezone(tz); 874 } else { 875 timezone = new GpxTimezone(TimeUnit.MILLISECONDS.toMinutes(TimeZone.getDefault().getRawOffset()) / 60.); //hours is double 876 } 821 877 } catch (ParseException e) { 822 878 timezone = GpxTimezone.ZERO; 823 879 Logging.trace(e); … … 1054 1110 if (selGpx == null) 1055 1111 return tr("No gpx selected"); 1056 1112 1057 final long offsetMs = ((long) (timezone.getHours() * TimeUnit.HOURS.toMillis( -1))) + delta.getMilliseconds(); // in milliseconds1113 final long offsetMs = ((long) (timezone.getHours() * TimeUnit.HOURS.toMillis(1))) + delta.getMilliseconds(); // in milliseconds 1058 1114 lastNumMatched = GpxImageCorrelation.matchGpxTrack(dateImgLst, selGpx.data, offsetMs, forceTags); 1059 1115 1060 1116 return trn("<html>Matched <b>{0}</b> of <b>{1}</b> photo to GPX track.</html>", -
src/org/openstreetmap/josm/tools/date/DateUtils.java
6 6 import java.text.SimpleDateFormat; 7 7 import java.time.DateTimeException; 8 8 import java.time.Instant; 9 import java.time.ZoneId;10 9 import java.time.ZoneOffset; 11 10 import java.time.ZonedDateTime; 12 11 import java.time.format.DateTimeFormatter; … … 100 99 parsePart2(str, 14), 101 100 parsePart2(str, 17), 102 101 0, 103 // consider EXIF date in default timezone 104 checkLayout(str, "xxxx:xx:xx xx:xx:xx") ? ZoneId.systemDefault() : ZoneOffset.UTC 102 ZoneOffset.UTC 105 103 ); 106 104 if (str.length() == 22 || str.length() == 25) { 107 105 final int plusHr = parsePart2(str, 20); … … 122 120 parsePart2(str, 14), 123 121 parsePart2(str, 17), 124 122 parsePart3(str, 20) * 1_000_000, 125 // consider EXIF date in default timezone 126 checkLayout(str, "xxxx:xx:xx xx:xx:xx.xxx") ? ZoneId.systemDefault() : ZoneOffset.UTC 123 ZoneOffset.UTC 127 124 ); 128 125 if (str.length() == 29) { 129 126 final int plusHr = parsePart2(str, 24);
